Relatively new to C and will readily concede there are things I think I understand, but probably don’t appreciate all the nuances. This is a MWE extracted from a more involved program I wrote. It compiles and runs fine, but testing reveals that the value of ev->pin is initially correct, but is incorrect after an unrelated function call (look for ??? in the code) Looks like the memory is getting stomped on somehow, but I cannot figure out what is going on.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define SCAN_EVENT_COUNT 5
#define PIN_ASSIGNMENTS {7, -1, 1, 13, 4}
#define EVENT_NAMES "first-second-third-fourth-fifth"
void init_scan_events();
int parse_string(char pInputString[],
char *Delimiter,
char *pToken[]);
struct scan_events
{
char event_names[31];
char *pEvent[SCAN_EVENT_COUNT];
int pin[SCAN_EVENT_COUNT];
};
int main(void)
{
init_scan_events();
return (0);
}
/**
* the following function from https://stackoverflow.com/a/2091906/633251
* Note that `strtok` expects a `char * string` and `char * delimiter` as arguments.
**/
int parse_string(char pInputString[],
char *Delimiter,
char *pToken[])
{
int i = 0;
pToken[i] = strtok(pInputString, Delimiter); // get first token
i++;
while ((pToken[i] = strtok(NULL, Delimiter)) != NULL) // get the rest of the tokens
{
i++;
}
return i;
}
void init_scan_events()
{
char en[] = EVENT_NAMES;
int en_size = strlen(en);
int size = SCAN_EVENT_COUNT;
int pin[] = PIN_ASSIGNMENTS;
int token_count = 0;
char *Delim = "-";
int i;
struct scan_events *ev = malloc(sizeof(struct scan_events));
if (ev == NULL)
{
printf("Allocation failed\n");
}
for (int i = 0; i < en_size; i++) // copy EVENT_NAMES
{
ev->event_names[i] = en[i];
}
for (int i = 0; i < size; i++) // copy PIN_ASSIGNMENTS
{
ev->pin[i] = pin[i];
}
for (int i = 0; i < size; i++)
{
printf("% d ", ev->pin[i]); // ??? inspect pin values: correct!
}
printf("\n");
token_count = parse_string(ev->event_names, Delim, ev->pEvent); // tokenize EVENT_NAMES
for (int i = 0; i < size; i++)
{
printf("% d ", ev->pin[i]); // ??? check pin values: corrupted!
}
printf("\n");
free(ev);
}
>Solution :
-
It’s a buffer overflow in
parse_string()for the assignmentpToken[5] = NULL. I suggest pass in SCAN_EVENT_COUNT and use that to limiti < 5. -
ev->event_namesmay not be ‘\0’ terminated. Either run the loop to<= en_sizeor usestrcpy(). -
sizeof EVENT_NAMES == 32 so
char event_names[31]is not big enough. -
If malloc fail you can’t use
ev. It’s not unreasonable toexit(1)as you probably can’t do anything about it anyways.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define DELIM "-"
#define SCAN_EVENT_COUNT 5
#define PIN_ASSIGNMENTS {7, -1, 1, 13, 4}
#define EVENT_NAMES "first-second-third-fourth-fifth"
void init_scan_events();
int parse_string(char pInputString[], const char *Delimiter, size_t n, char *pToken[]);
struct scan_events {
char event_names[sizeof EVENT_NAMES];
char *pEvent[SCAN_EVENT_COUNT];
int pin[SCAN_EVENT_COUNT];
};
void init_scan_events() {
int size = SCAN_EVENT_COUNT;
int pin[] = PIN_ASSIGNMENTS;
struct scan_events *ev = malloc(sizeof *ev);
if (!ev) {
printf("Allocation failed\n");
exit(1);
}
strcpy(ev->event_names, EVENT_NAMES);
for (int i = 0; i < size; i++) // copy PIN_ASSIGNMENTS
ev->pin[i] = pin[i];
for (int i = 0; i < size; i++)
printf("% d ", ev->pin[i]); // ??? inspect pin values: correct!
printf("\n");
int token_count = parse_string(ev->event_names, DELIM, SCAN_EVENT_COUNT, ev->pEvent); // tokenize EVENT_NAMES
for (int i = 0; i < size; i++)
printf("% d ", ev->pin[i]); // ??? check pin values: corrupted!
printf("\n");
free(ev);
}
int parse_string(char pInputString[], const char *Delimiter, size_t n, char *pToken[]) {
int i = 0;
for(; i < n; i++) {
pToken[i] = strtok(i ? NULL : pInputString, Delimiter); // get first token
if(!pToken[i]) break;
}
return i;
}
int main(void) {
init_scan_events();
}
and example run:
7 -1 1 13 4
7 -1 1 13 4