]> git.kaiwu.me - quickjs.git/commitdiff
faster and safer dbuf functions (#443)
authorFabrice Bellard <fabrice@bellard.org>
Mon, 13 Oct 2025 11:51:25 +0000 (13:51 +0200)
committerFabrice Bellard <fabrice@bellard.org>
Mon, 13 Oct 2025 11:51:25 +0000 (13:51 +0200)
cutils.c
cutils.h
libregexp.c
libunicode.c
quickjs.c

index c038cf44ca2cecf2bdde10f10b5d2021ced7acba..52ff1649bdb8073deeac18eaa1c8d4a9f4afa4f8 100644 (file)
--- a/cutils.c
+++ b/cutils.c
@@ -100,15 +100,20 @@ void dbuf_init(DynBuf *s)
     dbuf_init2(s, NULL, NULL);
 }
 
-/* return < 0 if error */
-int dbuf_realloc(DynBuf *s, size_t new_size)
+/* Try to allocate 'len' more bytes. return < 0 if error */
+int dbuf_claim(DynBuf *s, size_t len)
 {
-    size_t size;
+    size_t new_size, size;
     uint8_t *new_buf;
+    new_size = s->size + len;
+    if (new_size < len)
+        return -1; /* overflow case */
     if (new_size > s->allocated_size) {
         if (s->error)
             return -1;
-        size = s->allocated_size * 3 / 2;
+        size = s->allocated_size + (s->allocated_size / 2);
+        if (size < s->allocated_size)
+            return -1; /* overflow case */
         if (size > new_size)
             new_size = size;
         new_buf = s->realloc_func(s->opaque, s->buf, new_size);
@@ -122,22 +127,10 @@ int dbuf_realloc(DynBuf *s, size_t new_size)
     return 0;
 }
 
-int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
-{
-    size_t end;
-    end = offset + len;
-    if (dbuf_realloc(s, end))
-        return -1;
-    memcpy(s->buf + offset, data, len);
-    if (end > s->size)
-        s->size = end;
-    return 0;
-}
-
 int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
 {
-    if (unlikely((s->size + len) > s->allocated_size)) {
-        if (dbuf_realloc(s, s->size + len))
+    if (unlikely((s->allocated_size - s->size) < len)) {
+        if (dbuf_claim(s, len))
             return -1;
     }
     memcpy_no_ub(s->buf + s->size, data, len);
@@ -147,8 +140,8 @@ int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
 
 int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
 {
-    if (unlikely((s->size + len) > s->allocated_size)) {
-        if (dbuf_realloc(s, s->size + len))
+    if (unlikely((s->allocated_size - s->size) < len)) {
+        if (dbuf_claim(s, len))
             return -1;
     }
     memcpy(s->buf + s->size, s->buf + offset, len);
@@ -156,11 +149,26 @@ int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
     return 0;
 }
 
-int dbuf_putc(DynBuf *s, uint8_t c)
+int __dbuf_putc(DynBuf *s, uint8_t c)
 {
     return dbuf_put(s, &c, 1);
 }
 
+int __dbuf_put_u16(DynBuf *s, uint16_t val)
+{
+    return dbuf_put(s, (uint8_t *)&val, 2);
+}
+
+int __dbuf_put_u32(DynBuf *s, uint32_t val)
+{
+    return dbuf_put(s, (uint8_t *)&val, 4);
+}
+
+int __dbuf_put_u64(DynBuf *s, uint64_t val)
+{
+    return dbuf_put(s, (uint8_t *)&val, 8);
+}
+
 int dbuf_putstr(DynBuf *s, const char *str)
 {
     return dbuf_put(s, (const uint8_t *)str, strlen(str));
@@ -182,7 +190,7 @@ int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
         /* fast case */
         return dbuf_put(s, (uint8_t *)buf, len);
     } else {
-        if (dbuf_realloc(s, s->size + len + 1))
+        if (dbuf_claim(s, len + 1))
             return -1;
         va_start(ap, fmt);
         vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
index 9fcb7a60794e5ad099b15353c6bde2f958328027..094a8f124119ea179e3fe34586929a35402cf914 100644 (file)
--- a/cutils.h
+++ b/cutils.h
@@ -264,24 +264,58 @@ typedef struct DynBuf {
 
 void dbuf_init(DynBuf *s);
 void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
-int dbuf_realloc(DynBuf *s, size_t new_size);
-int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
+int dbuf_claim(DynBuf *s, size_t len);
 int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
 int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
-int dbuf_putc(DynBuf *s, uint8_t c);
 int dbuf_putstr(DynBuf *s, const char *str);
+int __dbuf_putc(DynBuf *s, uint8_t c);
+int __dbuf_put_u16(DynBuf *s, uint16_t val);
+int __dbuf_put_u32(DynBuf *s, uint32_t val);
+int __dbuf_put_u64(DynBuf *s, uint64_t val);
+
+static inline int dbuf_putc(DynBuf *s, uint8_t val)
+{
+    if (unlikely((s->allocated_size - s->size) < 1)) {
+        return __dbuf_putc(s, val);
+    } else {
+        s->buf[s->size++] = val;
+        return 0;
+    }
+}
+
 static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
 {
-    return dbuf_put(s, (uint8_t *)&val, 2);
+    if (unlikely((s->allocated_size - s->size) < 2)) {
+        return __dbuf_put_u16(s, val);
+    } else {
+        put_u16(s->buf + s->size, val);
+        s->size += 2;
+        return 0;
+    }
 }
+
 static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
 {
-    return dbuf_put(s, (uint8_t *)&val, 4);
+    if (unlikely((s->allocated_size - s->size) < 4)) {
+        return __dbuf_put_u32(s, val);
+    } else {
+        put_u32(s->buf + s->size, val);
+        s->size += 4;
+        return 0;
+    }
 }
+
 static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
 {
-    return dbuf_put(s, (uint8_t *)&val, 8);
+    if (unlikely((s->allocated_size - s->size) < 8)) {
+        return __dbuf_put_u64(s, val);
+    } else {
+        put_u64(s->buf + s->size, val);
+        s->size += 8;
+        return 0;
+    }
 }
+
 int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
                                                       const char *fmt, ...);
 void dbuf_free(DynBuf *s);
index 0cf9a1261d77adad1d94034b3d81d7ea6d5c5d73..118d950eb940df771a72703e10b17ca15124ccc1 100644 (file)
@@ -117,7 +117,7 @@ static inline int is_digit(int c) {
 /* insert 'len' bytes at position 'pos'. Return < 0 if error. */
 static int dbuf_insert(DynBuf *s, int pos, int len)
 {
-    if (dbuf_realloc(s, s->size + len))
+    if (dbuf_claim(s, len))
         return -1;
     memmove(s->buf + pos + len, s->buf + pos, s->size - pos);
     s->size += len;
@@ -2340,7 +2340,7 @@ static int re_parse_alternative(REParseState *s, BOOL is_backward_dir)
                speed is not really critical here) */
             end = s->byte_code.size;
             term_size = end - term_start;
-            if (dbuf_realloc(&s->byte_code, end + term_size))
+            if (dbuf_claim(&s->byte_code, term_size))
                 return -1;
             memmove(s->byte_code.buf + start + term_size,
                     s->byte_code.buf + start,
index 3791523d6a388bb10f90f844e0c389518275a01f..0c510ccb158d1d23f499e48d31955f2979df0747 100644 (file)
@@ -1179,7 +1179,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
     is_compat = n_type >> 1;
 
     dbuf_init2(dbuf, opaque, realloc_func);
-    if (dbuf_realloc(dbuf, sizeof(int) * src_len))
+    if (dbuf_claim(dbuf, sizeof(int) * src_len))
         goto fail;
 
     /* common case: latin1 is unaffected by NFC */
index 908cf0d25eaf6d7c6eae302d278d44f95fd14350..d1c5ed8135a299e1e5b0441d7ece207b1b2afb72 100644 (file)
--- a/quickjs.c
+++ b/quickjs.c
@@ -22835,7 +22835,7 @@ static void emit_op(JSParseState *s, uint8_t val)
 static void emit_atom(JSParseState *s, JSAtom name)
 {
     DynBuf *bc = &s->cur_func->byte_code;
-    if (dbuf_realloc(bc, bc->size + 4))
+    if (dbuf_claim(bc, 4))
         return; /* not enough memory : don't duplicate the atom */
     put_u32(bc->buf + bc->size, JS_DupAtom(s->ctx, name));
     bc->size += 4;
@@ -27751,7 +27751,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
         int chunk_size = pos_expr - pos_next;
         int offset = bc->size - pos_next;
         int i;
-        dbuf_realloc(bc, bc->size + chunk_size);
+        dbuf_claim(bc, chunk_size);
         dbuf_put(bc, bc->buf + pos_next, chunk_size);
         memset(bc->buf + pos_next, OP_nop, chunk_size);
         /* `next` part ends with a goto */
@@ -28157,7 +28157,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
                 int chunk_size = pos_body - pos_cont;
                 int offset = bc->size - pos_cont;
                 int i;
-                dbuf_realloc(bc, bc->size + chunk_size);
+                dbuf_claim(bc, chunk_size);
                 dbuf_put(bc, bc->buf + pos_cont, chunk_size);
                 memset(bc->buf + pos_cont, OP_nop, chunk_size);
                 /* increment part ends with a goto */
@@ -37097,7 +37097,7 @@ static int JS_WriteObjectAtoms(BCWriterState *s)
     /* XXX: could just append dbuf1 data, but it uses more memory if
        dbuf1 is larger than dbuf */
     atoms_size = s->dbuf.size;
-    if (dbuf_realloc(&dbuf1, dbuf1.size + atoms_size))
+    if (dbuf_claim(&dbuf1, atoms_size))
         goto fail;
     memmove(dbuf1.buf + atoms_size, dbuf1.buf, dbuf1.size);
     memcpy(dbuf1.buf, s->dbuf.buf, atoms_size);