Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Maddeningly, that episode never arrives at the actual bug. Via a thread the Mazda owner posted on Reddit, I found this great writeup: https://github.com/Hamled/mazda-format-string-bug#readme

TLDR: The problem is the `% In`, and specifically the `%n` - when printf sees that, it tries to store data in memory. Failing to do so, it crashes.



Oh god. Format string bugs in infotainment systems that can be triggered by careless radio stations. What could possibly go wrong.


This is so weird.

I read [1] which someone linked to, and it all seems to make sense. But it doeesn't!

I tried compiling this with gcc 11.2.0:

    #include <stdio.h>

    int main(void)
    {
      printf("%99 Invisible", NULL);
      return 0;
    }
And it won't compile. I get:

    test.c: In function ‘main’:
    test.c:5:14: warning: unknown conversion type character ‘ ’ in format [- 
   Wformat=]
        5 |   printf("%99 Invisible", NULL);
          |              ^
    test.c:5:10: warning: too many arguments for format [-Wformat-extra-args]
        5 |   printf("%99 Invisible", NULL);
          |          ^~~~~~~~~~~~~~~
which I would expect; you can't have a field width (the "99") and then the space-padding flag; flags go first. Also I can't find any coverage of %I (capital 'I', as in "Invisible") in the manual page for printf(3) on that system but that might just be an old manual page, GCC does seem to recognize it.

Removing the cruft and trying plain %In gives a warning, but I guess whoever built the car's radio UI ignores warnings.

I guess it's possible that the system doesn't use a standard-compliant enough C library, so it's printf() implementation does something ... creative with this string.

Anyway, classic case of the lovely foot-gunnery that is %n in the wild! Sorry for all the car owners, of course. :/

EDIT: A commenter pointed out that the above are "just warnings", oops. :) More oops on me for not spelling the freaking title correctly, of course it's "99%" and not "%99" .. .need more coffee, clearly. Sorry.

For people less used to C, the error here more or less seems to boil down to passing an untrusted string as the special "format string" for the printf() function. That function will interpret the contents of the string, and the percent symbol is how its special formatting directives start. Characters following a percent symbol will cause it to do stuff. The proper fix is usally to change

    printf(string);
to

    printf("%s", string);
or use some other I/O function altogether. The above simply says "here's a string", by using the programmer-selected string "%s" as the format, instead of the untrusted string coming from the outside.

[1] https://github.com/Hamled/mazda-format-string-bug#readme


The name of the podcast is "99% Invisible", not "%99 Invisible".

"99% Invisible" produces the expected result: https://godbolt.org/z/Mc9zPKWdq


You should also keep in mind that the string is essentially user input at runtime for the radio, so the compiler can't throw warnings or errors for it even if it wanted to.


Clang gives you this warning if you do that:

    <source>:6:12: warning: format string is not a string literal (potentially insecure) [-Wformat-security]


> And it won't compile.

Just are just warnings, it builds fine despite them.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: