Browse Source

PHP: Fix in upb for 32-bit platforms.

Joshua Haberman 4 years ago
parent
commit
314ce3c8a0
2 changed files with 38 additions and 21 deletions
  1. 22 11
      php/ext/google/protobuf/php-upb.c
  2. 16 10
      php/ext/google/protobuf/php-upb.h

+ 22 - 11
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;
 }

+ 16 - 10
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. */