Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

What's gone wrong with the values in this struct?

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 :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  1. It’s a buffer overflow in parse_string() for the assignment pToken[5] = NULL. I suggest pass in SCAN_EVENT_COUNT and use that to limit i < 5.

  2. ev->event_names may not be ‘\0’ terminated. Either run the loop to <= en_size or use strcpy().

  3. sizeof EVENT_NAMES == 32 so char event_names[31] is not big enough.

  4. If malloc fail you can’t use ev. It’s not unreasonable to exit(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 
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading