Fixed "NULL + 0" UB in JSON encoder and decoder.
diff --git a/upb/json_encode.c b/upb/json_encode.c
index d118c9b..9963008 100644
--- a/upb/json_encode.c
+++ b/upb/json_encode.c
@@ -35,6 +35,11 @@
const upb_msgdef *m, bool first);
static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
+static char *jsonenc_ptradd(char *ptr, size_t size) {
+ // Generates the same code as "ptr + size" but avoids UB of NULL + 0.
+ return size ? ptr + size : ptr;
+}
+
UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) {
upb_status_seterrmsg(e->status, msg);
longjmp(e->err, 1);
@@ -63,8 +68,10 @@
memcpy(e->ptr, data, len);
e->ptr += len;
} else {
- if (have) memcpy(e->ptr, data, have);
- e->ptr += have;
+ if (have) {
+ memcpy(e->ptr, data, have);
+ e->ptr += have;
+ }
e->overflow += (len - have);
}
}
@@ -86,7 +93,7 @@
if (UPB_LIKELY(have > n)) {
e->ptr += n;
} else {
- e->ptr += have;
+ if (have) e->ptr += have;
e->overflow += (n - have);
}
}
@@ -190,7 +197,7 @@
static const char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const unsigned char *ptr = (unsigned char*)str.data;
- const unsigned char *end = ptr + str.size;
+ const unsigned char *end = jsonenc_ptradd(ptr, str.size);
char buf[4];
jsonenc_putstr(e, "\"");
@@ -226,7 +233,7 @@
static void jsonenc_stringbody(jsonenc *e, upb_strview str) {
const char *ptr = str.data;
- const char *end = ptr + str.size;
+ const char *end = jsonenc_ptradd(ptr, str.size);
while (ptr < end) {
switch (*ptr) {
@@ -698,7 +705,7 @@
e.buf = buf;
e.ptr = buf;
- e.end = buf + size;
+ e.end = jsonenc_ptradd(buf, size);
e.overflow = 0;
e.options = options;
e.ext_pool = ext_pool;