Skip to content

sprintf / snprintf error #4174

@nuket

Description

@nuket

There's an error in sprintf and snprintf that occurs when more than 8 varargs are passed in after the format specifier.

The problem is that:

  • an extra '00' sneaks into the output string between the 1st and 2nd parameter outputs
  • the last parameter does not make it into the output string

This can lead to day-long debugging sessions of unrelated software modules, in order to determine the root cause.

Here's an example sketch that demonstrates what happens:

/**
 * Demonstrate that the sprintf / snprintf implementation on Arduino is broken.
 * 
 * sprintf / snprintf, when used with more than 8 varargs:
 *     inserts an extra '00' in the output string
 *     removes the last parameter from the output string
 * 
 * This causes a lot of extra debugging.
 * 
 * Expected: abcd0001020304050607
 * Actual:   abcd0000010203040506
 */

enum {
    OUTPUT_LENGTH = 50
};

uint32_t shortId   = 0xabcd;
uint8_t  buffer[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };

void setup() 
{
    Serial.begin(115200);

    char output[OUTPUT_LENGTH] = { 0 };

    // ERROR: The buggy way.
    //
    // Prints: abcd0000010203040506
    snprintf(output, OUTPUT_LENGTH, "%04x%02x%02x%02x%02x%02x%02x%02x%02x",
        shortId,
        buffer[0],
        buffer[1],
        buffer[2],
        buffer[3],
        buffer[4],
        buffer[5],
        buffer[6],
        buffer[7],
        buffer[8]);

    Serial.println(output);

    // OK: The way that actually works.
    //
    // Prints: abcd0001020304050607
    snprintf(output, OUTPUT_LENGTH, "%04x",
        shortId);

    snprintf(output + 4, OUTPUT_LENGTH - 4, "%02x%02x%02x%02x%02x%02x%02x%02x",
        buffer[0],
        buffer[1],
        buffer[2],
        buffer[3],
        buffer[4],
        buffer[5],
        buffer[6],
        buffer[7],
        buffer[8]);

    Serial.println(output);

    // ERROR: Another buggy way.
    //
    // Prints: abcd0000010203040506
    sprintf(output, "%04x%02x%02x%02x%02x%02x%02x%02x%02x",
        shortId,
        buffer[0],
        buffer[1],
        buffer[2],
        buffer[3],
        buffer[4],
        buffer[5],
        buffer[6],
        buffer[7],
        buffer[8]);

    Serial.println(output);
}

void loop() 
{
}

Metadata

Metadata

Assignees

Labels

Type: Works For MeWe are unable to reproduce the reported bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions