mirror of
https://github.com/ultrajson/ultrajson.git
synced 2024-04-20 05:03:48 +02:00
Add and fix debug memory checks for all buffer appends on encoding
In DEBUG mode, this ensures that all buffer appends are safe. It also refactors direct `memcpy` calls into a helper `Buffer_memcpy` function that ensures correct buffer pointer movement and has a similar safety check.
This commit is contained in:
parent
b3f8754c8a
commit
66060a0fab
|
@ -165,6 +165,20 @@ static void Buffer_Realloc (JSONObjectEncoder *enc, size_t cbNeeded)
|
|||
Buffer_Realloc((__enc), (__len));\
|
||||
} \
|
||||
|
||||
static void *Buffer_memcpy (JSONObjectEncoder *enc, const void *src, size_t n)
|
||||
{
|
||||
void *out;
|
||||
#ifdef DEBUG
|
||||
if ((size_t) (enc->end - enc->offset) < n) {
|
||||
fprintf(stderr, "Ran out of buffer space during Buffer_memcpy()\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
out = memcpy(enc->offset, src, n);
|
||||
enc->offset += n;
|
||||
return out;
|
||||
}
|
||||
|
||||
static FASTCALL_ATTR INLINE_PREFIX void FASTCALL_MSVC Buffer_AppendShortHexUnchecked (char *outputOffset, unsigned short value)
|
||||
{
|
||||
*(outputOffset++) = g_hexChars[(value & 0xf000) >> 12];
|
||||
|
@ -179,6 +193,13 @@ static int Buffer_EscapeStringUnvalidated (JSONObjectEncoder *enc, const char *i
|
|||
|
||||
for (;;)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// 6 is the maximum length of a single character (cf. RESERVE_STRING).
|
||||
if ((io < end) && (enc->end - of < 6)) {
|
||||
fprintf(stderr, "Ran out of buffer space during Buffer_EscapeStringUnvalidated()\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
switch (*io)
|
||||
{
|
||||
case 0x00:
|
||||
|
@ -285,11 +306,15 @@ static int Buffer_EscapeStringValidated (JSOBJ obj, JSONObjectEncoder *enc, cons
|
|||
for (;;)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// 6 is the maximum length of a single character (cf. RESERVE_STRING).
|
||||
if ((io < end) && (enc->end - of < 6)) {
|
||||
fprintf(stderr, "Ran out of buffer space during Buffer_EscapeStringValidated()\n");
|
||||
abort();
|
||||
}
|
||||
/*
|
||||
6 is the maximum length of a single character (cf. RESERVE_STRING).
|
||||
Note that the loop below may consume more than one input char and produce a UTF-16 surrogate pair.
|
||||
In that case, more than 6 characters would be needed on the output buffer.
|
||||
So this calculates the maximum length of the entire remaining input buffer instead. */
|
||||
if (enc->end - enc->offset < 6 * (end - io)) {
|
||||
fprintf(stderr, "Ran out of buffer space during Buffer_EscapeStringValidated()\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
JSUINT8 utflen = g_asciiOutputTable[(unsigned char) *io];
|
||||
|
||||
|
@ -562,6 +587,13 @@ static void Buffer_AppendLongUnchecked(JSONObjectEncoder *enc, JSINT64 value)
|
|||
JSUINT64 uvalue = (value < 0) ? -value : value;
|
||||
|
||||
wstr = enc->offset;
|
||||
#ifdef DEBUG
|
||||
// 20 is the maximum length of a JSINT64 (minus sign plus 19 digits)
|
||||
if (enc->end - enc->offset < 20) {
|
||||
fprintf(stderr, "Ran out of buffer space during Buffer_AppendLongUnchecked()\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
// Conversion. Number is reversed.
|
||||
|
||||
do *wstr++ = (char)(48 + (uvalue % 10ULL)); while(uvalue /= 10ULL);
|
||||
|
@ -578,6 +610,13 @@ static void Buffer_AppendUnsignedLongUnchecked(JSONObjectEncoder *enc, JSUINT64
|
|||
JSUINT64 uvalue = value;
|
||||
|
||||
wstr = enc->offset;
|
||||
#ifdef DEBUG
|
||||
// 21 is the maximum length of a JSUINT64 (minus sign plus 20 digits)
|
||||
if (enc->end - enc->offset < 21) {
|
||||
fprintf(stderr, "Ran out of buffer space during Buffer_AppendUnsignedLongUnchecked()\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
// Conversion. Number is reversed.
|
||||
|
||||
do *wstr++ = (char)(48 + (uvalue % 10ULL)); while(uvalue /= 10ULL);
|
||||
|
@ -591,14 +630,19 @@ static int Buffer_AppendDoubleDconv(JSOBJ obj, JSONObjectEncoder *enc, double va
|
|||
{
|
||||
char buf[128];
|
||||
int strlength;
|
||||
#ifdef DEBUG
|
||||
if ((size_t) (enc->end - enc->offset) < sizeof(buf)) {
|
||||
fprintf(stderr, "Ran out of buffer space during Buffer_AppendDoubleDconv()\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
if(!dconv_d2s(enc->d2s, value, buf, sizeof(buf), &strlength))
|
||||
{
|
||||
SetError (obj, enc, "Invalid value when encoding double");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(enc->offset, buf, strlength);
|
||||
enc->offset += strlength;
|
||||
Buffer_memcpy(enc, buf, strlength);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -894,8 +938,7 @@ static void encode(JSOBJ obj, JSONObjectEncoder *enc, const char *name, size_t c
|
|||
return;
|
||||
}
|
||||
|
||||
memcpy(enc->offset, value, szlen);
|
||||
enc->offset += szlen;
|
||||
Buffer_memcpy(enc, value, szlen);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue