| 36 | } |
| 37 | |
| 38 | static char *read_file(const char *path, int *out_len) { |
| 39 | FILE *f = cbm_fopen(path, "rb"); |
| 40 | if (!f) { |
| 41 | return NULL; |
| 42 | } |
| 43 | (void)fseek(f, 0, SEEK_END); |
| 44 | long size = ftell(f); |
| 45 | (void)fseek(f, 0, SEEK_SET); |
| 46 | if (size <= 0 || size > cbm_max_file_bytes()) { /* generous, env-configurable cap (B4) */ |
| 47 | (void)fclose(f); |
| 48 | return NULL; |
| 49 | } |
| 50 | /* +pad: tree-sitter lexer lookahead reads past EOF; keep it in-bounds */ |
| 51 | enum { CBM_TS_LOOKAHEAD_PAD = 16 }; |
| 52 | char *buf = malloc((size_t)size + CBM_TS_LOOKAHEAD_PAD); |
| 53 | if (!buf) { |
| 54 | (void)fclose(f); |
| 55 | return NULL; |
| 56 | } |
| 57 | size_t nread = fread(buf, SKIP_ONE, size, f); |
| 58 | (void)fclose(f); |
| 59 | if (nread > (size_t)size) { |
| 60 | nread = (size_t)size; |
| 61 | } |
| 62 | memset(buf + nread, 0, CBM_TS_LOOKAHEAD_PAD); |
| 63 | *out_len = (int)nread; |
| 64 | return buf; |
| 65 | } |
| 66 | |
| 67 | static const char *itoa_log(int val) { |
| 68 | enum { RING_BUF_COUNT = 4, RING_BUF_MASK = 3 }; |
no test coverage detected