T09 · Insecure Skill Coding Practices
Error
- Location
- code.c:27
- Finding
- Out-of-Bounds Frequency-Table Access for Non-Lowercase Input<![CDATA[ ## Vulnerability Details **File Location**: `code.c:27`, `code.c:43-46`, and `code.c:99` **Vulnerability Type**: Unchecked array indexing using attacker-controlled character values **Risk Level**: High ### Vulnerable Code ```c double calculate_redundancy(const char *text, int n) { int freq[ALPHABET_SIZE] = {0}; for (int i = 0; i < n && i < 10000; i++) { freq[text[i] - 'a']++; } double entropy = 0; for (int i = 0; i < ALPHABET_SIZE; i++) { if (freq[i] > 0) { double p = (double)freq[i] / 10000; entropy -= p * log2(p); } } double max_entropy = log2(ALPHABET_SIZE); return 1.0 - (entropy / max_entropy); } int find_rarest_char_pos(const char *pattern, int m, const int *text_freq) { int rarest_pos = 0; int min_freq = text_freq[pattern[0] - 'a']; for (int i = 1; i < m; i++) { int freq = text_freq[pattern[i] - 'a']; if (freq < min_freq) { min_freq = freq; rarest_pos = i; } } return rarest_pos; } ``` The same unsafe indexing occurs while sampling text in the adaptive search: ```c int text_freq[ALPHABET_SIZE] = {0}; for (int i = 0; i < sample_size; i++) { text_freq[text[i] - 'a']++; } ``` ### Technical Analysis `ALPHABET_SIZE` is 26, but text and pattern bytes are converted directly into indices by subtracting `'a'`. The code does not establish that each byte falls within the inclusive range `'a'` through `'z'`. For example, an uppercase `A`, punctuation, a null byte, or a byte whose `char` representation is negative can produce an index below zero or above 25. The resulting operations access memory outside the `freq` or `text_freq` arrays. The writes in `calculate_redundancy()` and `yijing_v3_search()` can corrupt stack memory, while the accesses in `find_rarest_char_pos()` can read outside the frequency table. The documentation describes general text processing and log analysis, so callers could rea ...[truncated 1091 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Use a frequency table covering every possible byte and convert each input byte to `unsigned char` before indexing: ```c #define BYTE_VALUES 256 size_t freq[BYTE_VALUES] = {0}; unsigned char value = (unsigned char)text[i]; freq[value]++; ``` Apply the same design consistently to text and pattern indexing. If the algorithm intentionally supports only lowercase ASCII, validate every byte first and return a documented error for unsupported input. Additional hardening should include: 1. Replace signed `int` lengths with `size_t` where practical. 2. Validate that pointers are non-null when their corresponding lengths are nonzero. 3. Clearly document the accepted character encoding and alphabet. 4. Add tests containing uppercase characters, punctuation, null bytes, bytes above `0x7f`, and platforms where `char` is signed. 5. Compile and test with AddressSanitizer and UndefinedBehaviorSanitizer. ]]>
