diff options
| author | peter <peter@pmikkelsen.com> | 2026-10-04 17:04:28 +0000 |
|---|---|---|
| committer | peter <peter@pmikkelsen.com> | 2026-10-04 17:04:28 +0000 |
| commit | c5a489d7f82535a70488dd4f9e40e79f32a7fb2f (patch) | |
| tree | 3f6e214b395d9655e054508128fcf373a6dfd39b /src | |
| parent | b66229d60635784ed289dd9bf0058f5c165ca8b5 (diff) | |
Fix the crashes found by the fuzzer so far.
I really need to think of a better way to store those crash inputs.
FossilOrigin-Name: a8b84fbc85ec0b472aca930d2d0af27949b39940317114cc37d37044bf1975d5
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/aplwc_internal.h | 1 | ||||
| -rw-r--r-- | src/lib/memory.c | 12 | ||||
| -rw-r--r-- | src/lib/module.c | 2 | ||||
| -rw-r--r-- | src/lib/string.c | 8 | ||||
| -rw-r--r-- | src/lib/syntax.c | 86 |
5 files changed, 50 insertions, 59 deletions
diff --git a/src/lib/aplwc_internal.h b/src/lib/aplwc_internal.h index ca7e719..148fd58 100644 --- a/src/lib/aplwc_internal.h +++ b/src/lib/aplwc_internal.h @@ -163,6 +163,7 @@ int valid_ref(struct aplwc_ref *); #define MEMPTRS_EXIT(aplwc) memptrs_remove(aplwc, &memptrs_frame) /* string.c */ +#define INVALID_CHAR UINT32_MAX struct string *chars_to_string(struct aplwc *, const char *, int len); uint32_t string_char(struct string *, size_t); size_t char_length(struct string *, size_t); diff --git a/src/lib/memory.c b/src/lib/memory.c index a8317c7..006c409 100644 --- a/src/lib/memory.c +++ b/src/lib/memory.c @@ -441,8 +441,7 @@ compact(struct aplwc *aplwc) static void * alloc(struct aplwc *aplwc, size_t size, enum chunk_tag tag) { - struct chunk *free; - struct chunk *new; + struct chunk *free, *new; size_t pad; int attempt; @@ -454,7 +453,7 @@ alloc(struct aplwc *aplwc, size_t size, enum chunk_tag tag) attempt = 0; retry: DEBUG(check_mem(aplwc)); - free = FAILCASE(find_free(aplwc, size), NULL); + new = free = FAILCASE(find_free(aplwc, size), NULL); if(!free){ switch(attempt++){ case 0: @@ -469,14 +468,12 @@ retry: /* fall-through */ default: aplwc->last_error = APLWC_OUT_OF_MEMORY; - return NULL; + goto end; } } assert(free->tag == CHUNK_TAG_FREE); - new = free; - if(free->size > (size + 2*HEADER_SIZE)){ free = (struct chunk *)(((uint8_t*)free) + HEADER_SIZE + size); free->tag = CHUNK_TAG_FREE; @@ -496,8 +493,9 @@ retry: new->tag = tag; new->reachable = aplwc->reachable_bit; +end: DEBUG(check_mem(aplwc)); - return data(new); + return new ? data(new) : NULL; } void diff --git a/src/lib/module.c b/src/lib/module.c index 9c2cbc2..22b8eac 100644 --- a/src/lib/module.c +++ b/src/lib/module.c @@ -28,8 +28,6 @@ add_member(struct aplwc *aplwc, struct aplwc_module *module, symbol_t name, stru for(m = module->members; m; m = m->link){ if(m->name == name){ - if(real_member) - assert(m->real_member == NULL || m->real_member == real_member); m->real_member = real_member; m->exported |= export; goto end; diff --git a/src/lib/string.c b/src/lib/string.c index 4101b80..0c01fca 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -104,6 +104,10 @@ string_char(struct string *string, size_t offset) uint32_t c; size_t len, i; + assert(offset <= string->bytes); + if(offset == string->bytes) + return INVALID_CHAR; + c = 0; len = char_length(string, offset); switch(char_length(string, offset)){ @@ -134,8 +138,8 @@ char_length(struct string *string, size_t offset) { uint8_t b; - if(offset >= string->bytes) - return 0; + assert(offset < string->bytes); + b = string->utf8[offset]; assert(!((b & 0xC0) == 0x80)); diff --git a/src/lib/syntax.c b/src/lib/syntax.c index 3354050..5b60fac 100644 --- a/src/lib/syntax.c +++ b/src/lib/syntax.c @@ -56,8 +56,10 @@ peek(struct scan_state *state) static uint32_t advance(struct scan_state *state) { - state->offset += char_length(*state->text, state->offset); - state->skip_number_and_identifier = 0; + if(peek(state) != INVALID_CHAR){ + state->offset += char_length(*state->text, state->offset); + state->skip_number_and_identifier = 0; + } return peek(state); } @@ -81,7 +83,7 @@ skip_space(struct scan_state *state) #define T tokens->tokens[token_index] static enum aplwc_rc -single_sym(struct scan_state *state, struct token_list *tokens, size_t token_index, int check_only) +single_sym(struct scan_state *state, struct token_list *tokens, size_t token_index) { uint32_t c; size_t start; @@ -110,11 +112,9 @@ single_sym(struct scan_state *state, struct token_list *tokens, size_t token_ind goto end; } T.tag = TOKEN_TAG_UNKNOWN_SYM; - if(!check_only){ - if((rc = newsym(state, start, 1, &sym)) != APLWC_OK) - goto end; - T.data.symbol = sym; - } + if((rc = newsym(state, start, 1, &sym)) != APLWC_OK) + goto end; + T.data.symbol = sym; break; } @@ -125,7 +125,7 @@ end: } static enum aplwc_rc -identifier(struct scan_state *state, struct token_list *tokens, size_t token_index, int check_only) +identifier(struct scan_state *state, struct token_list *tokens, size_t token_index) { uint32_t c; size_t start, len; @@ -148,11 +148,9 @@ identifier(struct scan_state *state, struct token_list *tokens, size_t token_ind }while(is_id_continue(c)); T.tag = TOKEN_TAG_IDENTIFIER; - if(!check_only){ - if((rc = newsym(state, start, len, &sym)) != APLWC_OK) - goto end; - T.data.symbol = sym; - } + if((rc = newsym(state, start, len, &sym)) != APLWC_OK) + goto end; + T.data.symbol = sym; state->skip_number_and_identifier = 1; rc = APLWC_OK; @@ -162,7 +160,7 @@ end: } static enum aplwc_rc -keyword(struct scan_state *state, struct token_list *tokens, size_t token_index, int check_only) +keyword(struct scan_state *state, struct token_list *tokens, size_t token_index) { uint32_t c; size_t start, len; @@ -180,35 +178,30 @@ keyword(struct scan_state *state, struct token_list *tokens, size_t token_index, c = advance(state); start = state->offset; - len = 0; - do{ - c = advance(state); + for(len = 0; is_id_continue(c); c = advance(state)) len++; - }while(is_id_continue(c)); rc = APLWC_OK; T.tag = TOKEN_TAG_KEYWORD; - if(!check_only){ - if((rc = newsym(state, start, len, &sym)) != APLWC_OK) - goto end; + if((rc = newsym(state, start, len, &sym)) != APLWC_OK) + goto end; - for(kw = 0; kw < N_KWDS; kw++){ - if(sym == state->aplwc->keyword_symbols[kw]){ - T.data.keyword = kw; - break; - } + for(kw = 0; kw < N_KWDS; kw++){ + if(sym == state->aplwc->keyword_symbols[kw]){ + T.data.keyword = kw; + break; } - if(kw == N_KWDS) - rc = APLWC_INVALID_SYNTAX; - } + if(kw == N_KWDS) + rc = APLWC_INVALID_SYNTAX; + end: MEMPTRS_EXIT(state->aplwc); return rc; } static enum aplwc_rc -number(struct scan_state *state, struct token_list *tokens, size_t token_index, int check_only) +number(struct scan_state *state, struct token_list *tokens, size_t token_index) { uint32_t c; int has_digits; @@ -217,8 +210,6 @@ number(struct scan_state *state, struct token_list *tokens, size_t token_index, MEMPTRS(state->aplwc, 1); MEMPTR(0, tokens); - UNUSED_PARAMETER(check_only); - rc = APLWC_INVALID_SYNTAX; c = peek(state); @@ -260,7 +251,7 @@ end: } static enum aplwc_rc -text(struct scan_state *state, struct token_list *tokens, size_t token_index, int check_only) +text(struct scan_state *state, struct token_list *tokens, size_t token_index) { uint32_t c; enum aplwc_rc rc; @@ -268,8 +259,6 @@ text(struct scan_state *state, struct token_list *tokens, size_t token_index, in MEMPTRS(state->aplwc, 1); MEMPTR(0, tokens); - UNUSED_PARAMETER(check_only); - rc = APLWC_INVALID_SYNTAX;; c = peek(state); if(c != '\'') @@ -277,7 +266,7 @@ text(struct scan_state *state, struct token_list *tokens, size_t token_index, in do c = advance(state); - while((c != '\n') && (c != 0) && (c != '\'')); + while((c != '\n') && (c != INVALID_CHAR) && (c != '\'')); if(c == '\'') advance(state); @@ -292,7 +281,7 @@ end: } static enum aplwc_rc -comment(struct scan_state *state, struct token_list *tokens, size_t token_index, int check_only) +comment(struct scan_state *state, struct token_list *tokens, size_t token_index) { uint32_t c; enum aplwc_rc rc; @@ -300,8 +289,6 @@ comment(struct scan_state *state, struct token_list *tokens, size_t token_index, MEMPTRS(state->aplwc, 1); MEMPTR(0, tokens); - UNUSED_PARAMETER(check_only); - rc = APLWC_INVALID_SYNTAX; c = peek(state); if(c != 0x235D) @@ -319,11 +306,11 @@ end: } static enum aplwc_rc -next_token(struct scan_state *state, struct token_list *tokens, size_t token_index, int check_only) +next_token(struct scan_state *state, struct token_list *tokens, size_t token_index) { enum aplwc_rc rc; size_t i; - enum aplwc_rc (*scans[])(struct scan_state *, struct token_list *, size_t, int) = { + enum aplwc_rc (*scans[])(struct scan_state *, struct token_list *, size_t) = { identifier, keyword, number, @@ -338,12 +325,12 @@ next_token(struct scan_state *state, struct token_list *tokens, size_t token_ind T.start = state->offset; rc = APLWC_INVALID_SYNTAX; for(i = 0; (rc == APLWC_INVALID_SYNTAX) && (i < NELEM(scans)); i++){ - rc = scans[i](state, tokens, token_index, check_only); + rc = scans[i](state, tokens, token_index); switch(rc){ case APLWC_OK: break; case APLWC_INVALID_SYNTAX: - state->offset = tokens->tokens[token_index].start; + state->offset = T.start; break; default: goto end; @@ -374,11 +361,13 @@ check(struct aplwc *aplwc, struct string *text, size_t *n) goto end; } MEMPTR(1, tokens); + tokens->text = text; + tokens->length = 1; init_scan_state(&state, aplwc, &text); - for(count = 0; peek(&state); count++){ - ret = next_token(&state, tokens, 0, 1); + for(count = 0; peek(&state) != INVALID_CHAR; count++){ + ret = next_token(&state, tokens, 0); if(ret != APLWC_OK) goto end; } @@ -404,8 +393,9 @@ scan(struct aplwc *aplwc, struct string *text, struct token_list *tokens) init_scan_state(&state, aplwc, &text); ret = APLWC_OK; - for(count = 0; (ret == APLWC_OK) && peek(&state); count++){ - ret = next_token(&state, tokens, count, 0); + for(count = 0; (ret == APLWC_OK) && (peek(&state) != INVALID_CHAR); count++){ + assert(count < tokens->length); + ret = next_token(&state, tokens, count); } MEMPTRS_EXIT(aplwc); |