T09 · Insecure Skill Coding Practices
Warning
- Location
- checklist.h:36
- Finding
- Unchecked String Pointers Cause Undefined Behavior<![CDATA[ ## Vulnerability Details **File Location**: `checklist.h`, lines 36-66 and 86-95 **Vulnerability Type**: Unchecked pointer use in formatted output **Risk Level**: Medium ### Vulnerable Code ```c void check_null_pointer(void* ptr, const char* var_name) { printf("[check] Null pointer: %s\n", var_name); if (ptr == NULL) { printf("[warning] Null pointer\n"); printf("[remediation] Add a NULL check\n"); printf("if (%s != NULL) { ... }\n", var_name); } else { printf("[pass]\n"); } } void check_memory_leak(const char* alloc_func, const char* free_func) { printf("[check] Memory leak\n"); printf("Allocation function: %s\n", alloc_func); printf("Release function: %s\n", free_func); if (free_func == NULL || strlen(free_func) == 0) { printf("[warning] No corresponding release function found\n"); } else { printf("[pass]\n"); } } void check_race_condition(const char* shared_resource) { printf("[check] Race condition: %s\n", shared_resource); /* Additional checklist output omitted because it does not affect the flaw. */ } void check_uninitialized(const char* var_name, const char* init_value) { printf("[check] Uninitialized variable: %s\n", var_name); if (init_value == NULL) { printf("[warning] Variable is uninitialized\n"); printf("%s = 0; or %s = NULL;\n", var_name, var_name); } else { printf("[pass] %s = %s\n", var_name, init_value); } } ``` The displayed message text is translated into English, while the pointer handling and control flow reproduce the audited implementation. ### Technical Analysis The public functions accept string pointers from callers and pass them directly to the `%s` conversion of `printf` without first confirming that the pointers are non-null and reference valid, null-terminated strings. In `check_memory_leak`, `free_func` is checked for `NULL` only after it has already been passed to `printf`. The ...[truncated 2155 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Validate every string pointer before its first use. - Substitute a fixed safe label when an optional argument is null. - Define whether each parameter is mandatory or optional in the API contract. - Require valid, null-terminated strings with lifetimes covering the entire function call. - Where string lengths are known, use bounded output such as `printf("%.*s", length, value)` after validating the pointer and length. - Add unit tests covering null, empty, unterminated, and invalid-lifetime inputs. - Compile and test with AddressSanitizer and UndefinedBehaviorSanitizer. A basic null-safe pattern is: ```c static const char *safe_string(const char *value) { return value != NULL ? value : "(null)"; } void check_memory_leak(const char *alloc_func, const char *free_func) { printf("Allocation function: %s\n", safe_string(alloc_func)); printf("Release function: %s\n", safe_string(free_func)); if (free_func == NULL || free_func[0] == '\0') { printf("No corresponding release function was supplied.\n"); } } ``` Null checks do not make arbitrary dangling or unterminated pointers safe. Callers must still satisfy a documented ownership and validity contract. ]]>
