diff --git a/tests/bindings/lua/test_upb.lua b/tests/bindings/lua/test_upb.lua index 87bdba674f..b44c595dd1 100644 --- a/tests/bindings/lua/test_upb.lua +++ b/tests/bindings/lua/test_upb.lua @@ -481,6 +481,13 @@ function test_numeric_map() end end +function test_unknown() + local bytes = string.rep("\x38\x00", 10000) + for i=1,1000 do + local msg = upb.decode(test_messages_proto3.TestAllTypesProto3, bytes) + end +end + function test_foo() local symtab = upb.SymbolTable() local filename = "external/com_google_protobuf/descriptor_proto-descriptor-set.proto.bin" diff --git a/upb/msg.c b/upb/msg.c index c878be9777..5f6d1ce170 100644 --- a/upb/msg.c +++ b/upb/msg.c @@ -36,11 +36,12 @@ bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, in->unknown->len = 0; } else if (in->unknown->size - in->unknown->len < len) { size_t need = in->unknown->len + len; - size_t size = in->unknown->size;; + size_t size = in->unknown->size; while (size < need) size *= 2; in->unknown = upb_arena_realloc( arena, in->unknown, in->unknown->size + overhead, size + overhead); if (!in->unknown) return false; + in->unknown->size = size; } memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len); in->unknown->len += len; diff --git a/upb/port_def.inc b/upb/port_def.inc index 7371b6d456..2dafc3d99e 100644 --- a/upb/port_def.inc +++ b/upb/port_def.inc @@ -181,3 +181,25 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #else #define UPB_NAN (0.0 / 0.0) #endif + +#if defined(__SANITIZE_ADDRESS__) +#define UPB_ASAN 1 +#ifdef __cplusplus +extern "C" { +#endif +void __asan_poison_memory_region(void const volatile *addr, size_t size); +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#ifdef __cplusplus +} /* extern "C" */ +#endif +#define UPB_POISON_MEMORY_REGION(addr, size) \ + __asan_poison_memory_region((addr), (size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + __asan_unpoison_memory_region((addr), (size)) +#else +#define UPB_ASAN 0 +#define UPB_POISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#endif diff --git a/upb/port_undef.inc b/upb/port_undef.inc index c2b5f4a322..5a11ca6397 100644 --- a/upb/port_undef.inc +++ b/upb/port_undef.inc @@ -26,3 +26,6 @@ #undef _upb_snprintf #undef _upb_vsnprintf #undef _upb_va_copy +#undef UPB_POISON_MEMORY_REGION +#undef UPB_UNPOISON_MEMORY_REGION +#undef UPB_ASAN diff --git a/upb/upb.c b/upb/upb.c index eb32ba2517..e0d34b54b4 100644 --- a/upb/upb.c +++ b/upb/upb.c @@ -114,7 +114,7 @@ static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr, a->head.end = UPB_PTR_AT(block, size, char); a->cleanups = &block->cleanups; - /* TODO(haberman): ASAN poison. */ + UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr); } static bool upb_arena_allocblock(upb_arena *a, size_t size) { @@ -127,14 +127,9 @@ static bool upb_arena_allocblock(upb_arena *a, size_t size) { return true; } -static bool arena_has(upb_arena *a, size_t size) { - _upb_arena_head *h = (_upb_arena_head*)a; - return (size_t)(h->end - h->ptr) >= size; -} - void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */ - UPB_ASSERT(arena_has(a, size)); + UPB_ASSERT(_upb_arenahas(a, size)); return upb_arena_malloc(a, size); } @@ -229,14 +224,15 @@ void upb_arena_free(upb_arena *a) { bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) { cleanup_ent *ent; - if (!a->cleanups || !arena_has(a, sizeof(cleanup_ent))) { + if (!a->cleanups || !_upb_arenahas(a, sizeof(cleanup_ent))) { if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */ - UPB_ASSERT(arena_has(a, sizeof(cleanup_ent))); + UPB_ASSERT(_upb_arenahas(a, sizeof(cleanup_ent))); } a->head.end -= sizeof(cleanup_ent); ent = (cleanup_ent*)a->head.end; (*a->cleanups)++; + UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent)); ent->cleanup = func; ent->ud = ud; diff --git a/upb/upb.h b/upb/upb.h index e1d9d8cfd3..f5c440e0ee 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -161,17 +161,35 @@ void *_upb_arena_slowmalloc(upb_arena *a, size_t size); UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } +UPB_INLINE bool _upb_arenahas(upb_arena *a, size_t size) { + _upb_arena_head *h = (_upb_arena_head*)a; + return (size_t)(h->end - h->ptr) >= size; +} + UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { _upb_arena_head *h = (_upb_arena_head*)a; void* ret; size = UPB_ALIGN_MALLOC(size); - if (UPB_UNLIKELY((size_t)(h->end - h->ptr) < size)) { + if (UPB_UNLIKELY(!_upb_arenahas(a, size))) { return _upb_arena_slowmalloc(a, size); } ret = h->ptr; h->ptr += size; + UPB_UNPOISON_MEMORY_REGION(ret, size); + +#if UPB_ASAN + { + size_t guard_size = 32; + if (_upb_arenahas(a, guard_size)) { + h->ptr += guard_size; + } else { + h->ptr = h->end; + } + } +#endif + return ret; }