From e0716abc81b0590b1ef5094445f790e728595c00 Mon Sep 17 00:00:00 2001 From: Mid <> Date: Tue, 7 Oct 2025 12:27:21 +0300 Subject: [PATCH] Handle indefinite elements --- eebie/reader.c | 21 +++++++++++++++++++-- eebie/reader.h | 5 +++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/eebie/reader.c b/eebie/reader.c index 45c14f5..1482903 100644 --- a/eebie/reader.c +++ b/eebie/reader.c @@ -9,6 +9,8 @@ #include"reader.h" +#define is_max(u) ((u) == 0xFFFFFFFFFFFFFFFFUL) + void ebml_reader_init(EBMLReader *this) { memset(this, 0, sizeof(*this)); this->state = EBMLRS_WAITING_FOR_ELEMENT_ID; @@ -89,6 +91,10 @@ static int get_varint(const uint8_t *data, size_t length, uint64_t *result) { if(ret >= 0) { *result &= ~VARINT_MASKS[ret]; + + if(*result == (1UL << (ret * 7)) - 1) { + *result = 0xFFFFFFFFFFFFFFFFUL; + } } return ret; @@ -137,7 +143,7 @@ int ebml_reader_feed(EBMLReader *this, const uint8_t *data, size_t length) { } this->idStack[this->currentDepth] = this->inside.id; - this->stack[this->currentDepth] = elLength + status; + this->stack[this->currentDepth] = is_max(elLength) ? elLength : elLength + status; this->currentDepth++; @@ -156,7 +162,9 @@ int ebml_reader_feed(EBMLReader *this, const uint8_t *data, size_t length) { } for(int i = 0; i < this->currentDepth; i++) { - this->stack[i] -= eaten; + if(!is_max(this->stack[i])) { + this->stack[i] -= eaten; + } } while(this->currentDepth > 0 && this->stack[this->currentDepth - 1] == 0) { @@ -173,3 +181,12 @@ int ebml_reader_feed(EBMLReader *this, const uint8_t *data, size_t length) { return eaten; } + +void ebml_reader_leave(EBMLReader *this, uint64_t id) { + for(int i = 0; i < this->currentDepth; i++) { + if(this->idStack[i] == id) { + this->currentDepth = i; + return; + } + } +} diff --git a/eebie/reader.h b/eebie/reader.h index 6330f2b..61af8b6 100644 --- a/eebie/reader.h +++ b/eebie/reader.h @@ -49,6 +49,11 @@ typedef struct EBMLReader { void ebml_reader_init(EBMLReader*); int ebml_reader_feed(EBMLReader*, const uint8_t *data, size_t length); +// Because Eebie is schemaless, it must be told when we have left an +// indefinite element, otherwise the stack may grow indefinitely and +// even overflow. The user may call this from eventEnterElement. +void ebml_reader_leave(EBMLReader*, uint64_t id); + #ifdef __cplusplus } #endif