mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Ensure palmdoc decompress does nto write out of bounds. Fixes #2022035 [Private bug](https://bugs.launchpad.net/calibre/+bug/2022035)
This commit is contained in:
parent
b454da1636
commit
eb80c90221
@ -42,10 +42,19 @@ typedef struct {
|
||||
|
||||
#define CHAR(x) (( (x) > 127 ) ? (x)-256 : (x))
|
||||
|
||||
static bool
|
||||
write_to_bytes_object(PyObject **output, Py_ssize_t pos, char ch) {
|
||||
if (pos >= PyBytes_GET_SIZE(*output)) {
|
||||
if (_PyBytes_Resize(output, 2 * pos) != 0) return false;
|
||||
}
|
||||
PyBytes_AS_STRING(*output)[pos] = ch;
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
cpalmdoc_decompress(PyObject *self, PyObject *args) {
|
||||
const char *_input = NULL; Py_ssize_t input_len = 0;
|
||||
Byte *input; char *output; Byte c; PyObject *ans;
|
||||
Byte *input; Byte c; PyObject *ans;
|
||||
Py_ssize_t i = 0, o = 0, j = 0, di, n;
|
||||
if (!PyArg_ParseTuple(args, "y#", &_input, &input_len))
|
||||
return NULL;
|
||||
@ -54,31 +63,29 @@ cpalmdoc_decompress(PyObject *self, PyObject *args) {
|
||||
// Map chars to bytes
|
||||
for (j = 0; j < input_len; j++)
|
||||
input[j] = (_input[j] < 0) ? _input[j]+256 : _input[j];
|
||||
output = (char *)PyMem_Malloc(sizeof(char)*(MAX(BUFFER, 8*input_len)));
|
||||
if (output == NULL) return PyErr_NoMemory();
|
||||
ans = PyBytes_FromStringAndSize(NULL, 8*input_len);
|
||||
if (ans == NULL) { PyMem_Free(input); return NULL; }
|
||||
|
||||
#define write(ch) if (!write_to_bytes_object(&ans, o++, ch)) { PyMem_Free(input); return NULL; }
|
||||
while (i < input_len) {
|
||||
c = input[i++];
|
||||
if (c >= 1 && c <= 8) // copy 'c' bytes
|
||||
while (c--) output[o++] = (char)input[i++];
|
||||
|
||||
else if (c <= 0x7F) // 0, 09-7F = self
|
||||
output[o++] = (char)c;
|
||||
|
||||
else if (c >= 0xC0) { // space + ASCII char
|
||||
output[o++] = ' ';
|
||||
output[o++] = c ^ 0x80;
|
||||
}
|
||||
else { // 80-BF repeat sequences
|
||||
if (c >= 1 && c <= 8) { // copy 'c' bytes
|
||||
while (c--) { write(input[i++]); }
|
||||
} else if (c <= 0x7F) { // 0, 09-7F = self
|
||||
write((char)c);
|
||||
} else if (c >= 0xC0) { // space + ASCII char
|
||||
write(' '); write(c ^ 0x80);
|
||||
} else { // 80-BF repeat sequences
|
||||
c = (c << 8) + input[i++];
|
||||
di = (c & 0x3FFF) >> 3;
|
||||
for ( n = (c & 7) + 3; n--; ++o )
|
||||
output[o] = output[o - di];
|
||||
for ( n = (c & 7) + 3; n--; ++o ) {
|
||||
if (!write_to_bytes_object(&ans, o, PyBytes_AS_STRING(ans)[o-di])) { PyMem_Free(input); return NULL; }
|
||||
}
|
||||
}
|
||||
}
|
||||
ans = Py_BuildValue("y#", output, o);
|
||||
if (output != NULL) PyMem_Free(output);
|
||||
#undef write
|
||||
if (input != NULL) PyMem_Free(input);
|
||||
if (_PyBytes_Resize(&ans, o) != 0) return NULL;
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user