snprintf.c 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /* https://cirosantilli.com/linux-kernel-module-cheat#c
  2. *
  3. * Like `sprintf`, but writes at most n bytes, so it is safer,
  4. * because it may not be possible or easy to calculate the resulting
  5. * size of a formated string.
  6. *
  7. * The size given includes the null terminator. */
  8. #include <assert.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. int main(void) {
  13. #if __STDC_VERSION__ >= 199901L
  14. /* Common usage when string fits.
  15. *
  16. * Ensures that there will be no out or bounds access on out. */
  17. {
  18. int in = 1234;
  19. char out[1024];
  20. int snprintf_return;
  21. snprintf_return = snprintf(out, sizeof(out), "ab%dcd", in);
  22. /* The usual error checking. */
  23. if (snprintf_return < 0) {
  24. perror("snprintf");
  25. exit(EXIT_FAILURE);
  26. }
  27. assert((size_t)snprintf_return < sizeof(out));
  28. /* Assert because we know the return here. */
  29. assert(snprintf_return == 8);
  30. /* What it actually copied. */
  31. assert(strcmp(out, "ab1234cd") == 0);
  32. }
  33. /* Less common case where string does not fit. Error handling would
  34. * normally follow in a real program. */
  35. {
  36. int in = 1234;
  37. char out[6];
  38. /* The return here is the same as before.
  39. *
  40. * Because it is >= than the imposed limit of 6, we know that
  41. * the write failed to fully complete. */
  42. assert(snprintf(out, sizeof(out), "ab%dcd", in) == 8);
  43. assert(strcmp(out, "ab123") == 0);
  44. }
  45. #endif
  46. return EXIT_SUCCESS;
  47. }