Merge pull request #350 from haberman/encode-depthlimit

Added depth limit checking to upb_encode().
pull/13171/head
Joshua Haberman 4 years ago committed by GitHub
commit 31b3528424
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      tests/bindings/lua/test_upb.lua
  2. 12
      upb/encode.c
  3. 2
      upb/encode.h

@ -700,6 +700,12 @@ function test_json_emit_defaults()
local json = upb.json_encode(msg, {upb.JSONENC_EMITDEFAULTS}) local json = upb.json_encode(msg, {upb.JSONENC_EMITDEFAULTS})
end end
function test_encode_depth_limit()
local msg = test_messages_proto3.TestAllTypesProto3()
msg.recursive_message = msg
assert_error(function() upb.encode(msg) end)
end
function test_gc() function test_gc()
local top = test_messages_proto3.TestAllTypesProto3() local top = test_messages_proto3.TestAllTypesProto3()
local n = 100 local n = 100

@ -33,6 +33,7 @@ typedef struct {
upb_alloc *alloc; upb_alloc *alloc;
char *buf, *ptr, *limit; char *buf, *ptr, *limit;
int options; int options;
int depth;
_upb_mapsorter sorter; _upb_mapsorter sorter;
} upb_encstate; } upb_encstate;
@ -217,9 +218,11 @@ static void encode_scalar(upb_encstate *e, const void *_field_mem,
if (submsg == NULL) { if (submsg == NULL) {
return; return;
} }
if (--e->depth == 0) encode_err(e);
encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP); encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
encode_message(e, submsg, subm, &size); encode_message(e, submsg, subm, &size);
wire_type = UPB_WIRE_TYPE_START_GROUP; wire_type = UPB_WIRE_TYPE_START_GROUP;
e->depth++;
break; break;
} }
case UPB_DESCRIPTOR_TYPE_MESSAGE: { case UPB_DESCRIPTOR_TYPE_MESSAGE: {
@ -229,9 +232,11 @@ static void encode_scalar(upb_encstate *e, const void *_field_mem,
if (submsg == NULL) { if (submsg == NULL) {
return; return;
} }
if (--e->depth == 0) encode_err(e);
encode_message(e, submsg, subm, &size); encode_message(e, submsg, subm, &size);
encode_varint(e, size); encode_varint(e, size);
wire_type = UPB_WIRE_TYPE_DELIMITED; wire_type = UPB_WIRE_TYPE_DELIMITED;
e->depth++;
break; break;
} }
default: default:
@ -312,6 +317,7 @@ static void encode_array(upb_encstate *e, const char *field_mem,
const void *const*start = _upb_array_constptr(arr); const void *const*start = _upb_array_constptr(arr);
const void *const*ptr = start + arr->len; const void *const*ptr = start + arr->len;
const upb_msglayout *subm = m->submsgs[f->submsg_index]; const upb_msglayout *subm = m->submsgs[f->submsg_index];
if (--e->depth == 0) encode_err(e);
do { do {
size_t size; size_t size;
ptr--; ptr--;
@ -319,12 +325,14 @@ static void encode_array(upb_encstate *e, const char *field_mem,
encode_message(e, *ptr, subm, &size); encode_message(e, *ptr, subm, &size);
encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP); encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
} while (ptr != start); } while (ptr != start);
e->depth++;
return; return;
} }
case UPB_DESCRIPTOR_TYPE_MESSAGE: { case UPB_DESCRIPTOR_TYPE_MESSAGE: {
const void *const*start = _upb_array_constptr(arr); const void *const*start = _upb_array_constptr(arr);
const void *const*ptr = start + arr->len; const void *const*ptr = start + arr->len;
const upb_msglayout *subm = m->submsgs[f->submsg_index]; const upb_msglayout *subm = m->submsgs[f->submsg_index];
if (--e->depth == 0) encode_err(e);
do { do {
size_t size; size_t size;
ptr--; ptr--;
@ -332,6 +340,7 @@ static void encode_array(upb_encstate *e, const char *field_mem,
encode_varint(e, size); encode_varint(e, size);
encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED); encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
} while (ptr != start); } while (ptr != start);
e->depth++;
return; return;
} }
} }
@ -437,10 +446,13 @@ static void encode_message(upb_encstate *e, const char *msg,
char *upb_encode_ex(const void *msg, const upb_msglayout *m, int options, char *upb_encode_ex(const void *msg, const upb_msglayout *m, int options,
upb_arena *arena, size_t *size) { upb_arena *arena, size_t *size) {
upb_encstate e; upb_encstate e;
unsigned depth = (unsigned)options >> 16;
e.alloc = upb_arena_alloc(arena); e.alloc = upb_arena_alloc(arena);
e.buf = NULL; e.buf = NULL;
e.limit = NULL; e.limit = NULL;
e.ptr = NULL; e.ptr = NULL;
e.depth = depth ? depth : 64;
e.options = options; e.options = options;
_upb_mapsorter_init(&e.sorter); _upb_mapsorter_init(&e.sorter);
char *ret = NULL; char *ret = NULL;

@ -27,6 +27,8 @@ enum {
UPB_ENCODE_SKIPUNKNOWN = 2, UPB_ENCODE_SKIPUNKNOWN = 2,
}; };
#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options, char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
upb_arena *arena, size_t *size); upb_arena *arena, size_t *size);

Loading…
Cancel
Save