Skip to content

Commit aada0ed

Browse files
committed
gh-156939: Fix xmlcharrefreplace() buffer overflow
Write into a temporay buffer to not write the trailing NUL byte.
1 parent 23180c5 commit aada0ed

3 files changed

Lines changed: 18 additions & 4 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix a buffer overflow the ``xmlcharrefreplace`` error handler of 8-bit
2+
encoding (such as ``ascii`` and ``latin1``). Previously, a buffer overflow
3+
of one NUL byte was written in the stack memory if the output length was
4+
exactly 512 bytes. Patch by Victor Stinner.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix a buffer overflow in the ``xmlcharrefreplace`` error handler of 8-bit
2+
encoding (such as ``ascii`` and ``latin1``). Previously, a buffer overflow
3+
wrote one NUL byte in the stack memory if the output length was exactly 512
4+
bytes. Patch by Victor Stinner.

Objects/unicodeobject.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -879,10 +879,16 @@ xmlcharrefreplace(PyBytesWriter *writer, char *str,
879879

880880
/* generate replacement */
881881
for (i = collstart; i < collend; ++i) {
882-
size = sprintf(str, "&#%d;", PyUnicode_READ(kind, data, i));
883-
if (size < 0) {
884-
return NULL;
885-
}
882+
// Use snprintf() with a temporary buffer to not write the trailing
883+
// NUL byte in the writer buffer.
884+
Py_BUILD_ASSERT(_Py_MAX_UNICODE <= 0x10ffff);
885+
// len('&#1114111;\0') is 11 bytes.
886+
char buffer[11];
887+
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
888+
size = snprintf(buffer, sizeof(buffer), "&#%d;", ch);
889+
assert(5 <= size && (size_t)size <= (sizeof(buffer) - 1));
890+
891+
memcpy(str, buffer, size);
886892
str += size;
887893
}
888894
return str;

0 commit comments

Comments
 (0)