Handle indefinite elements

This commit is contained in:
Mid 2025-10-07 12:27:21 +03:00
parent 8b0fbfdcf7
commit e0716abc81
2 changed files with 24 additions and 2 deletions

View File

@ -9,6 +9,8 @@
#include"reader.h" #include"reader.h"
#define is_max(u) ((u) == 0xFFFFFFFFFFFFFFFFUL)
void ebml_reader_init(EBMLReader *this) { void ebml_reader_init(EBMLReader *this) {
memset(this, 0, sizeof(*this)); memset(this, 0, sizeof(*this));
this->state = EBMLRS_WAITING_FOR_ELEMENT_ID; 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) { if(ret >= 0) {
*result &= ~VARINT_MASKS[ret]; *result &= ~VARINT_MASKS[ret];
if(*result == (1UL << (ret * 7)) - 1) {
*result = 0xFFFFFFFFFFFFFFFFUL;
}
} }
return ret; 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->idStack[this->currentDepth] = this->inside.id;
this->stack[this->currentDepth] = elLength + status; this->stack[this->currentDepth] = is_max(elLength) ? elLength : elLength + status;
this->currentDepth++; 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++) { 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) { 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; 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;
}
}
}

View File

@ -49,6 +49,11 @@ typedef struct EBMLReader {
void ebml_reader_init(EBMLReader*); void ebml_reader_init(EBMLReader*);
int ebml_reader_feed(EBMLReader*, const uint8_t *data, size_t length); 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 #ifdef __cplusplus
} }
#endif #endif