Merge pull request #15109 from s-hadinger/berry_allow_null_bytes_ptr

Berry allow bytes() mapped region to hold a null pointer
This commit is contained in:
s-hadinger 2022-03-12 11:11:11 +01:00 committed by GitHub
commit 4211450967
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 19 deletions

View File

@ -403,6 +403,9 @@ static bbool buf_equals(buf_impl* buf1, buf_impl* buf2)
// we know that both buf1 and buf2 are non-null // we know that both buf1 and buf2 are non-null
if (buf1->len != buf2->len) { return bfalse; } if (buf1->len != buf2->len) { return bfalse; }
size_t len = buf1->len; size_t len = buf1->len;
if (!buf1->bufptr && !buf2->bufptr) { return btrue; } /* if both are null then considered equal */
if (!buf1->bufptr || !buf2->bufptr) { return bfalse; } /* if only one is null, then not equal */
/* here none of the pointer are null */
for (uint32_t i=0; i<len; i++) { for (uint32_t i=0; i<len; i++) {
if (buf_get1(buf1, i) != buf_get1(buf2, i)) { return bfalse; } if (buf_get1(buf1, i) != buf_get1(buf2, i)) { return bfalse; }
} }
@ -433,6 +436,13 @@ static void buf_add_hex(buf_impl* attr, const char *hex, size_t len)
** Wrapping into lib ** Wrapping into lib
********************************************************************/ ********************************************************************/
/* if the bufptr is null, don't try to dereference and raise an exception instead */
static void check_ptr(bvm *vm, buf_impl* attr) {
if (!attr->bufptr) {
be_raise(vm, "value_error", "operation not allowed on <null> pointer");
}
}
/* load instance attribute into a single structure, and store 'previous' values in order to later update only the changed ones */ /* load instance attribute into a single structure, and store 'previous' values in order to later update only the changed ones */
/* stack item 1 must contain the instance */ /* stack item 1 must contain the instance */
buf_impl m_read_attributes(bvm *vm, int idx) buf_impl m_read_attributes(bvm *vm, int idx)
@ -681,6 +691,7 @@ static int m_tostring(bvm *vm)
max_len = be_toint(vm, 2); /* you can specify the len as second argument, or 0 for unlimited */ max_len = be_toint(vm, 2); /* you can specify the len as second argument, or 0 for unlimited */
} }
buf_impl attr = m_read_attributes(vm, 1); buf_impl attr = m_read_attributes(vm, 1);
if (attr.bufptr) { /* pointer looks valid */
int32_t len = attr.len; int32_t len = attr.len;
if (max_len > 0 && len > max_len) { if (max_len > 0 && len > max_len) {
len = max_len; /* limit output size */ len = max_len; /* limit output size */
@ -698,6 +709,9 @@ static int m_tostring(bvm *vm)
be_pushnstring(vm, hex_out, l); /* make escape string from buffer */ be_pushnstring(vm, hex_out, l); /* make escape string from buffer */
be_remove(vm, -2); /* remove buffer */ be_remove(vm, -2); /* remove buffer */
} else { /* pointer is null, don't try to dereference it as it would crash */
be_pushstring(vm, "bytes(<null>)");
}
be_return(vm); be_return(vm);
} }
@ -707,6 +721,7 @@ static int m_tostring(bvm *vm)
static int m_asstring(bvm *vm) static int m_asstring(bvm *vm)
{ {
buf_impl attr = bytes_check_data(vm, 0); buf_impl attr = bytes_check_data(vm, 0);
check_ptr(vm, &attr);
be_pushnstring(vm, (const char*) attr.bufptr, attr.len); be_pushnstring(vm, (const char*) attr.bufptr, attr.len);
be_return(vm); be_return(vm);
} }
@ -718,6 +733,7 @@ static int m_fromstring(bvm *vm)
const char *s = be_tostring(vm, 2); const char *s = be_tostring(vm, 2);
int32_t len = be_strlen(vm, 2); /* calling be_strlen to support null chars in string */ int32_t len = be_strlen(vm, 2); /* calling be_strlen to support null chars in string */
buf_impl attr = bytes_check_data(vm, 0); buf_impl attr = bytes_check_data(vm, 0);
check_ptr(vm, &attr);
if (attr.fixed && attr.len != len) { if (attr.fixed && attr.len != len) {
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
} }
@ -745,6 +761,7 @@ static int m_add(bvm *vm)
{ {
int argc = be_top(vm); int argc = be_top(vm);
buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */ buf_impl attr = bytes_check_data(vm, 4); /* we reserve 4 bytes anyways */
check_ptr(vm, &attr);
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
if (argc >= 2 && be_isint(vm, 2)) { if (argc >= 2 && be_isint(vm, 2)) {
int32_t v = be_toint(vm, 2); int32_t v = be_toint(vm, 2);
@ -781,6 +798,7 @@ static int m_get(bvm *vm, bbool sign)
{ {
int argc = be_top(vm); int argc = be_top(vm);
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
check_ptr(vm, &attr);
if (argc >=2 && be_isint(vm, 2)) { if (argc >=2 && be_isint(vm, 2)) {
int32_t idx = be_toint(vm, 2); int32_t idx = be_toint(vm, 2);
int vsize = 1; int vsize = 1;
@ -839,6 +857,7 @@ static int m_set(bvm *vm)
{ {
int argc = be_top(vm); int argc = be_top(vm);
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
check_ptr(vm, &attr);
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) { if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
int32_t idx = be_toint(vm, 2); int32_t idx = be_toint(vm, 2);
int32_t value = be_toint(vm, 3); int32_t value = be_toint(vm, 3);
@ -867,6 +886,7 @@ static int m_setitem(bvm *vm)
{ {
int argc = be_top(vm); int argc = be_top(vm);
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
check_ptr(vm, &attr);
if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) { if (argc >=3 && be_isint(vm, 2) && be_isint(vm, 3)) {
int index = be_toint(vm, 2); int index = be_toint(vm, 2);
int val = be_toint(vm, 3); int val = be_toint(vm, 3);
@ -884,6 +904,7 @@ static int m_item(bvm *vm)
{ {
int argc = be_top(vm); int argc = be_top(vm);
buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */ buf_impl attr = bytes_check_data(vm, 0); /* we reserve 4 bytes anyways */
check_ptr(vm, &attr);
if (argc >=2 && be_isint(vm, 2)) { /* single byte */ if (argc >=2 && be_isint(vm, 2)) { /* single byte */
int index = be_toint(vm,2); int index = be_toint(vm,2);
if (index < 0) { if (index < 0) {
@ -970,12 +991,15 @@ static int m_merge(bvm *vm)
{ {
int argc = be_top(vm); int argc = be_top(vm);
buf_impl attr = m_read_attributes(vm, 1); /* no resize yet */ buf_impl attr = m_read_attributes(vm, 1); /* no resize yet */
check_ptr(vm, &attr);
if (argc >= 2 && be_isbytes(vm, 2)) { if (argc >= 2 && be_isbytes(vm, 2)) {
buf_impl attr2 = m_read_attributes(vm, 2); buf_impl attr2 = m_read_attributes(vm, 2);
check_ptr(vm, &attr2);
/* allocate new object */ /* allocate new object */
bytes_new_object(vm, attr.len + attr2.len); bytes_new_object(vm, attr.len + attr2.len);
buf_impl attr3 = m_read_attributes(vm, -1); buf_impl attr3 = m_read_attributes(vm, -1);
check_ptr(vm, &attr3);
buf_add_buf(&attr3, &attr); buf_add_buf(&attr3, &attr);
buf_add_buf(&attr3, &attr2); buf_add_buf(&attr3, &attr2);
@ -990,8 +1014,10 @@ static int m_merge(bvm *vm)
static int m_copy(bvm *vm) static int m_copy(bvm *vm)
{ {
buf_impl attr = m_read_attributes(vm, 1); buf_impl attr = m_read_attributes(vm, 1);
check_ptr(vm, &attr);
bytes_new_object(vm, attr.len); bytes_new_object(vm, attr.len);
buf_impl attr2 = m_read_attributes(vm, -1); buf_impl attr2 = m_read_attributes(vm, -1);
check_ptr(vm, &attr2);
buf_add_buf(&attr2, &attr); buf_add_buf(&attr2, &attr);
m_write_attributes(vm, -1, &attr2); /* update instance */ m_write_attributes(vm, -1, &attr2); /* update instance */
be_return(vm); /* return self */ be_return(vm); /* return self */
@ -1002,6 +1028,7 @@ static int m_connect(bvm *vm)
{ {
int argc = be_top(vm); int argc = be_top(vm);
buf_impl attr = m_read_attributes(vm, 1); buf_impl attr = m_read_attributes(vm, 1);
check_ptr(vm, &attr);
if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); } if (attr.fixed) { be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); }
if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2))) { if (argc >= 2 && (be_isbytes(vm, 2) || be_isint(vm, 2))) {
if (be_isint(vm, 2)) { if (be_isint(vm, 2)) {
@ -1012,6 +1039,7 @@ static int m_connect(bvm *vm)
be_return(vm); /* return self */ be_return(vm); /* return self */
} else { } else {
buf_impl attr2 = m_read_attributes(vm, 2); buf_impl attr2 = m_read_attributes(vm, 2);
check_ptr(vm, &attr2);
bytes_resize(vm, &attr, attr.len + attr2.len); /* resize buf1 for total size */ bytes_resize(vm, &attr, attr.len + attr2.len); /* resize buf1 for total size */
buf_add_buf(&attr, &attr2); buf_add_buf(&attr, &attr2);
m_write_attributes(vm, 1, &attr); /* update instance */ m_write_attributes(vm, 1, &attr); /* update instance */
@ -1062,6 +1090,7 @@ static int m_nequal(bvm *vm)
static int m_tob64(bvm *vm) static int m_tob64(bvm *vm)
{ {
buf_impl attr = m_read_attributes(vm, 1); buf_impl attr = m_read_attributes(vm, 1);
check_ptr(vm, &attr);
int32_t len = attr.len; int32_t len = attr.len;
int32_t b64_len = encode_base64_length(len) + 1; /* size of base64 encoded string for this binary length, add NULL terminator */ int32_t b64_len = encode_base64_length(len) + 1; /* size of base64 encoded string for this binary length, add NULL terminator */
@ -1086,6 +1115,7 @@ static int m_fromb64(bvm *vm)
int32_t bin_len = decode_base64_length((unsigned char*)s); /* do a first pass to calculate the buffer size */ int32_t bin_len = decode_base64_length((unsigned char*)s); /* do a first pass to calculate the buffer size */
buf_impl attr = m_read_attributes(vm, 1); buf_impl attr = m_read_attributes(vm, 1);
check_ptr(vm, &attr);
if (attr.fixed && attr.len != bin_len) { if (attr.fixed && attr.len != bin_len) {
be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE); be_raise(vm, BYTES_RESIZE_ERROR, BYTES_RESIZE_MESSAGE);
} }
@ -1158,6 +1188,7 @@ BERRY_API void * be_pushbytes(bvm *vm, const void * bytes, size_t len)
{ {
bytes_new_object(vm, len); bytes_new_object(vm, len);
buf_impl attr = m_read_attributes(vm, -1); buf_impl attr = m_read_attributes(vm, -1);
check_ptr(vm, &attr);
if ((int32_t)len > attr.size) { len = attr.size; } /* double check if the buffer allocated was smaller */ if ((int32_t)len > attr.size) { len = attr.size; } /* double check if the buffer allocated was smaller */
if (bytes) { /* if bytes is null, buffer is filled with zeros */ if (bytes) { /* if bytes is null, buffer is filled with zeros */
memmove((void*)attr.bufptr, bytes, len); memmove((void*)attr.bufptr, bytes, len);
@ -1175,6 +1206,7 @@ BERRY_API const void *be_tobytes(bvm *vm, int rel_index, size_t *len)
int index = be_absindex(vm, rel_index); int index = be_absindex(vm, rel_index);
if (be_isbytes(vm, index)) { if (be_isbytes(vm, index)) {
buf_impl attr = m_read_attributes(vm, index); buf_impl attr = m_read_attributes(vm, index);
check_ptr(vm, &attr);
if (len) { *len = attr.len; } if (len) { *len = attr.len; }
return (void*) attr.bufptr; return (void*) attr.bufptr;
} }

View File

@ -13,6 +13,7 @@
#include "be_debug.h" #include "be_debug.h"
#include "be_map.h" #include "be_map.h"
#include "be_vm.h" #include "be_vm.h"
#include "be_var.h"
#include <string.h> #include <string.h>
#if BE_USE_GLOBAL_MODULE #if BE_USE_GLOBAL_MODULE

View File

@ -121,6 +121,8 @@ BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size)
} }
BERRY_API void* be_move_to_aligned(bvm *vm, void *ptr, size_t size) { BERRY_API void* be_move_to_aligned(bvm *vm, void *ptr, size_t size) {
(void)vm;
(void)size;
#if BE_USE_MEM_ALIGNED #if BE_USE_MEM_ALIGNED
if (size <= POOL32_SIZE) { if (size <= POOL32_SIZE) {
return ptr; /* if in memory pool, don't move it so be_free() will continue to work */ return ptr; /* if in memory pool, don't move it so be_free() will continue to work */
@ -303,7 +305,6 @@ BERRY_API void be_gc_free_memory_pools(bvm *vm) {
gc16_t* pool_to_freed = pool16; gc16_t* pool_to_freed = pool16;
pool16 = pool16->next; pool16 = pool16->next;
be_os_free(pool_to_freed); be_os_free(pool_to_freed);
pool16 = pool16->next;
} }
vm->gc.pool16 = NULL; vm->gc.pool16 = NULL;
@ -312,12 +313,12 @@ BERRY_API void be_gc_free_memory_pools(bvm *vm) {
gc32_t* pool_to_freed = pool32; gc32_t* pool_to_freed = pool32;
pool32 = pool32->next; pool32 = pool32->next;
be_os_free(pool_to_freed); be_os_free(pool_to_freed);
pool32 = pool32->next;
} }
vm->gc.pool32 = NULL; vm->gc.pool32 = NULL;
} }
/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */ /* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */
static int pop0(uint32_t n) __attribute__((unused));
static int pop0(uint32_t n) { static int pop0(uint32_t n) {
n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u); n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u); n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);

View File

@ -172,7 +172,7 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
break; break;
case BE_REAL: case BE_REAL:
#if BE_USE_SINGLE_FLOAT #if BE_USE_SINGLE_FLOAT
logfmt("be_const_real_hex(0x%08X)", (uint32_t) var_toobj(value)); logfmt("be_const_real_hex(%08" PRIX32 ")", (uint32_t)(uintptr_t)var_toobj(value));
#else #else
logfmt("be_const_real_hex(0x%016" PRIx64 ")", (uint64_t)var_toobj(value)); logfmt("be_const_real_hex(0x%016" PRIx64 ")", (uint64_t)var_toobj(value));
#endif #endif