We use the sscanf()
function under the eCos operating system to parse a command-line command provided by the user. We have code that essentially does this:
char[20] arg1 = "";
float arg2;
char[20] arg3 = "";
int n = sscanf(buffer + offset, "%4s %f %3s", arg1, &arg2, arg3); // offset is length of command plus 1 for the space
if (n == 3) { /* success */ } else { /* error */ };
But when called with a command buffer containing command arg1 40.0
, the success
branch is entered even though only two arguments were provided to the command. We would have expected the error
branch to be executed.
Using plenty of printf()
statements, here are the values of the variables after the call to sscanf()
:
buffer = "command arg1 40.0"
arg1 = "arg1"
arg2 = 40.0
arg3 = ""
We are unable to reproduce this behavior with unit tests. Before we start suspecting a broken sscanf()
implementation, can there be another explanation?
UPDATE
The eCos operating system implements its own version of the C standard library. Below is the code fragment that handles the %s
format specifier. I don't know if it helps but we are more and more confident there might be a bug here.
139 #define CT_STRING 2 /* %s conversion */
....
487 switch (c)
....
597 case CT_STRING:
598 /* like CCL, but zero-length string OK, & no NOSKIP */
599 if (width == 0)
600 width = ~0;
601 if (flags & SUPPRESS)
602 {
603 n = 0;
604 while (!isspace (*CURR_POS))
605 {
606 n++, INC_CURR_POS;
607 if (--width == 0)
608 break;
609 if (BufferEmpty)
610 break;
611 }
612 nread += n;
613 }
614 else
615 {
616 p0 = p = va_arg (ap, char *);
617 while (!isspace (*CURR_POS))
618 {
619 *p++ = *CURR_POS;
620 INC_CURR_POS;
621 if (--width == 0)
622 break;
623 if (BufferEmpty)
624 break;
625 }
626 *p = 0;
627 nread += p - p0;
628 nassigned++;
629 }
630 continue;