Search code examples
stdstm32mbedplatformiognu-arm

How could SSCANF provide so strange results?


I am in 4-day fight with this code:

  unsigned long baudrate = 0;
  unsigned char databits = 0;
  unsigned char stop_bits = 0;

  char parity_text[10];
  char flowctrl_text[4];

  const char xformat[] = "%lu,%hhu,%hhu,%[^,],%[^,]\n";
  const char xtext[] = "115200,8,1,EVEN,NFC\n";
  int res = sscanf(xtext, xformat, &baudrate, &databits, &stop_bits, (char*) &parity_text, (char*) &flowctrl_text);

  printf("Res: %d\r\n", res);
  printf("baudrate: %lu, databits: %hhu, stop: %hhu,   \r\n", baudrate, databits, stop_bits);
  printf("parity: %s \r\n", parity_text);
  printf("flowctrl: %s \r\n", flowctrl_text);

It returns:

Res: 5
baudrate: 115200, databits: 0, stop: 1,
parity:
flowctrl: NFC

Databits and parity missing !

Actually memory under the parity variable is '\0'VEN'\0', looks like the first characters was somehow overwritten by sscanf procedure.

Return value of sscanf is 5, which suggests, that it was able to parse the input.

My configuration:

  • gccarmnoneeabi 7.2.1
  • Visual Studio Code 1.43.2
  • PlatformIO Core 4.3.1
  • PlatformIO Home 3.1.1
  • Lib ST-STM 6.0.0 (Mbed 5.14.1)
  • STM32F446RE (Nucleo-F446RE)

I have tried (without success):

  • compiling with mbed RTOS and without
  • variable types uint8_t, uint32_t
  • gccarm versions: 6.3.1, 8.3.1, 9.2.1
  • using another IDE (CLion+PlatformIO)
  • compiling on another computer (same config)

What actually helps:

  • making the variables static
  • compiling in Mbed online compiler

The behavior of sscanf is as whole very unpredictable, mixing the order or datatype of variables sometimes helps, but most often ends with another flaws in the output.


Solution

  • This took me longer than I care to admit. But like most issues it ended up being very simple.

      char parity_text[10];
      char flowctrl_text[4];
    

    Needs to be changed to:

      char parity_text[10] = {0};
      char flowctrl_text[5] = {0};
    

    The flowctrl_text array is not large enough at size four to hold "EVEN" and the NULL termination. If you bump it to a size of 5 you should have no problem. Just to be safe I would also initialize the arrays to 0.

    Once I increased the size I had 0 issues with your existing code. Let me know if this helps.