diff options
| author | eunhhu <[email protected]> | 2026-09-27 23:38:54 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-27 23:38:54 +0100 |
| commit | ad27f1f5a4fc7a53d116feb9b1e2352239147fe0 (patch) | |
| tree | 85c2bca2056d9b62d4057f4fed82f1fcbb6cd959 /store/store-tree.c | |
| parent | 72f8e1ca1fba181eeed6d2643a21f05881272d83 (diff) | |
| download | pure-ad27f1f5a4fc7a53d116feb9b1e2352239147fe0.tar.gz pure-ad27f1f5a4fc7a53d116feb9b1e2352239147fe0.zip | |
Let a runtime-owned state grow past the document limit
A list's stored form is one value in the tree store, so the limit on a
document (1.38 MiB, what a host carries whole as an HTTP body) capped a
table at about 51,000 rows of 28 bytes. A value the runtime owns, a state
(a key starting with '.') or a draft without a key, may now grow to 1 GiB;
documents keep their limit. The store's format is unchanged: its trees
already reach far past either.
Diffstat (limited to 'store/store-tree.c')
| -rw-r--r-- | store/store-tree.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/store/store-tree.c b/store/store-tree.c index 024809b..0f83f27 100644 --- a/store/store-tree.c +++ b/store/store-tree.c @@ -879,6 +879,12 @@ static bool write_root(const Tree *tree, Writer *writer, Entry *root, bool reloc return root_height(tree, *root, &height) && write_subtree(tree, writer, root, height, relocate); } +/* How large a value under key may grow: a runtime-owned state's ('.', or no + * key at all) or a document's (store.h). */ +static uint64_t limit_of(const char *key) { + return !key[0] || key[0] == '.' ? PURE_STATE_LIMIT : PURE_OBJECT_LIMIT; +} + static bool read_record(const Tree *tree, Entry catalog, uint64_t index, unsigned char record[RECORD], Entry *document, int64_t *revision) { unsigned height; @@ -888,7 +894,7 @@ static bool read_record(const Tree *tree, Entry catalog, uint64_t index, uint64_t stored = decode64(record + KEY + 16); *revision = (int64_t)stored; return stored && stored <= (uint64_t)INT64_MAX && !document->ref == !document->bytes && - document->bytes <= PURE_OBJECT_LIMIT; + document->bytes <= limit_of((const char *)record); } /* Binary search over records ordered by their zero-padded key bytes. */ @@ -1579,7 +1585,7 @@ static void collect(PureDraft *draft) { PureResult pure_draft_splice(PureDraft *draft, size_t offset, size_t remove, PureSpan insert) { uint64_t size = draft->root.bytes; if (insert.size && !insert.data) return PURE_INVALID; - if (offset > size || remove > size - offset || insert.size > PURE_OBJECT_LIMIT - (size - remove)) + if (offset > size || remove > size - offset || insert.size > limit_of(draft->key) - (size - remove)) return PURE_LIMIT; if (!remove && !insert.size) return PURE_OK; Entry next; |
