Skip to content

Issue in int_to_string during calibration #1

Description

@TimVosch

Bug observed IRL, AI determined bug report, seems plausible cause.

No, it has a correctness bug around the decimal placement, plus a couple of smaller concerns.

The main bug: missing zero padding when k < 10^precision.

The loop only inserts the . (and a leading '0') once decimals reaches precision. If k runs out of digits before that, the decimal point is never written and no zeros are padded. Concrete cases with precision = 2:

  • k = 5 → you get "5", should be "0.05"
  • k = 9 → you get "9", should be "0.09"
  • k = 50 → works: "0.50"
  • k = 500 → works: "5.00"

So it's correct only when k >= 10^(precision-1). For inputs below that threshold it silently drops the decimal point and the leading digits.

The k == 0 early return also ignores precision.

It just writes '0' and returns, so int_to_string(0, 2, NULL) gives "0" instead of "0.00". Whether that matters depends on your contract for the function, but it's inconsistent with the non-zero path.

No explicit NUL terminator.

The function never writes '\0'. It works today only because:

  1. The static internal_buf is zero-initialized and position 20 is never overwritten (the loop always writes to positions < buf_len).
  2. A caller-supplied buf must already be NUL-terminated at index buf_len, and must be at least buf_len + 1 bytes — that precondition isn't documented anywhere.

I'd write buf[buf_len] = '\0'; explicitly at the top. It's free and removes a landmine.

Minor stuff:

  • _int_to_string — identifiers beginning with an underscore at file scope are reserved by the C standard (C11 §7.1.3). Use a trailing underscore or a module prefix instead.
  • The static scratch buffer makes this non-reentrant and means two overlapping calls with buf == NULL will stomp on each other. Probably fine in a single-threaded embedded context, but worth noting.
  • decimals could be uint8_t to match precision and avoid the signed/unsigned mix in the comparison (the compiler will promote, so it's not a real bug — just tidier).

A fix for the padding bug is to continue the loop (or a second loop) until both k == 0 and decimals > precision:

while (k > 0 || decimals <= precision) {
    char decimal = 0x30 + (k % 10);
    k /= 10;
    *ptr-- = decimal;
    decimals++;
    if (decimals == precision)
        *ptr-- = '.';
}

That naturally handles k == 0 with any precision (producing "0.00" etc.), so you can also drop the if (k == 0) early return entirely. Trace it for k=5, precision=2: writes '5', '0', ., '0'"0.05". ✓

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions