diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index a8945a5682..738386890b 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -761,7 +761,8 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, int ndx = field->descriptortype; if (_upb_isrepeated(field)) ndx += 18; ptr = decode_varint32(d, ptr, &val.size); - if (val.size >= INT32_MAX || ptr - d->end + val.size > d->limit) { + if (val.size >= INT32_MAX || + ptr - d->end + (int32_t)val.size > d->limit) { decode_err(d); /* Length overflow. */ } op = delim_ops[ndx]; @@ -1301,7 +1302,7 @@ static const size_t overhead = sizeof(upb_msg_internal); static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { ptrdiff_t size = sizeof(upb_msg_internal); - return UPB_PTR_AT(msg, -size, upb_msg_internal); + return (upb_msg_internal*)((char*)msg - size); } upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) { @@ -1401,13 +1402,16 @@ void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size, bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value, int elem_size_lg2, upb_arena *arena) { upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena); - size_t elem = arr->len; - char *data; + if (!arr) return false; - if (!arr || !_upb_array_resize(arr, elem + 1, arena)) return false; + size_t elems = arr->len; - data = _upb_array_ptr(arr); - memcpy(data + (elem << elem_size_lg2), value, 1 << elem_size_lg2); + if (!_upb_array_resize(arr, elems + 1, arena)) { + return false; + } + + char *data = _upb_array_ptr(arr); + memcpy(data + (elems << elem_size_lg2), value, 1 << elem_size_lg2); return true; } @@ -5337,10 +5341,14 @@ static const upb_filedef *_upb_symtab_addfile( upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, const upb_msglayout **layouts, upb_status *status) { upb_arena *file_arena = upb_arena_new(); - upb_filedef *file = upb_arena_malloc(file_arena, sizeof(*file)); - bool ok = true; + upb_filedef *file; symtab_addctx ctx; + if (!file_arena) return NULL; + + file = upb_arena_malloc(file_arena, sizeof(*file)); + if (!file) goto done; + ctx.file = file; ctx.symtab = s; ctx.file_arena = file_arena; @@ -5354,8 +5362,8 @@ static const upb_filedef *_upb_symtab_addfile( if (UPB_UNLIKELY(setjmp(ctx.err))) { UPB_ASSERT(!upb_ok(status)); - ok = false; remove_filedef(s, file); + file = NULL; } else { build_filedef(&ctx, file, file_proto); upb_strtable_insert3(&s->files, file->name, strlen(file->name), @@ -5364,8 +5372,9 @@ static const upb_filedef *_upb_symtab_addfile( upb_arena_fuse(s->arena, file_arena); } +done: upb_arena_free(file_arena); - return ok ? file : NULL; + return file; } const upb_filedef *upb_symtab_addfile( @@ -6246,6 +6255,8 @@ static void jsondec_resize(jsondec *d, char **buf, char **end, char **buf_end) { size_t size = UPB_MAX(8, 2 * oldsize); *buf = upb_arena_realloc(d->arena, *buf, len, size); + if (!*buf) jsondec_err(d, "Out of memory"); + *end = *buf + len; *buf_end = *buf + size; } diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index 9562de6945..d22b4aa0e0 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -506,7 +506,7 @@ UPB_INLINE uint64_t _upb_be_swap64(uint64_t val) { } UPB_INLINE int _upb_lg2ceil(int x) { - if (x == 0) return 0; + if (x <= 1) return 0; #ifdef __GNUC__ return 32 - __builtin_clz(x - 1); #else @@ -1043,7 +1043,8 @@ UPB_INLINE upb_msg *_upb_msg_new_inl(const upb_msglayout *l, upb_arena *a) { upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a); UPB_INLINE upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { - return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal); + ptrdiff_t size = sizeof(upb_msg_internal); + return (upb_msg_internal*)((char*)msg - size); } /* Clears the given message. */ @@ -1138,9 +1139,11 @@ typedef struct { uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */ size_t len; /* Measured in elements. */ size_t size; /* Measured in elements. */ + uint64_t junk; } upb_array; UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) { + UPB_ASSERT((arr->data & 7) <= 4); return (void*)(arr->data & ~(uintptr_t)7); } @@ -1150,15 +1153,17 @@ UPB_INLINE void *_upb_array_ptr(upb_array *arr) { UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) { UPB_ASSERT(elem_size_lg2 <= 4); + UPB_ASSERT(((uintptr_t)ptr & 7) == 0); return (uintptr_t)ptr | (unsigned)elem_size_lg2; } UPB_INLINE upb_array *_upb_array_new(upb_arena *a, size_t init_size, int elem_size_lg2) { + const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_array), 8); const size_t bytes = sizeof(upb_array) + (init_size << elem_size_lg2); upb_array *arr = (upb_array*)upb_arena_malloc(a, bytes); if (!arr) return NULL; - arr->data = _upb_tag_arrptr(arr + 1, elem_size_lg2); + arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2); arr->len = 0; arr->size = init_size; return arr; @@ -1331,17 +1336,17 @@ UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) { } } -UPB_INLINE upb_value _upb_map_tovalue(const void *val, size_t size, - upb_arena *a) { - upb_value ret = {0}; +UPB_INLINE bool _upb_map_tovalue(const void *val, size_t size, upb_value *msgval, + upb_arena *a) { if (size == UPB_MAPTYPE_STRING) { upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp)); + if (!strp) return false; *strp = *(upb_strview*)val; - ret = upb_value_ptr(strp); + *msgval = upb_value_ptr(strp); } else { - memcpy(&ret, val, size); + memcpy(msgval, val, size); } - return ret; + return true; } UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { @@ -1383,7 +1388,8 @@ UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) { UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size, void *val, size_t val_size, upb_arena *arena) { upb_strview strkey = _upb_map_tokey(key, key_size); - upb_value tabval = _upb_map_tovalue(val, val_size, arena); + upb_value tabval = {0}; + if (!_upb_map_tovalue(val, val_size, &tabval, arena)) return false; upb_alloc *a = upb_arena_alloc(arena); /* TODO(haberman): add overwrite operation to minimize number of lookups. */