fix_parsing_long_lines 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. Description: Fix parsing of lines longer than 2047 characters
  2. If a line in /etc/hosts.{allow,deny} is longer than BUFLEN-1 (2047)
  3. characters then len will be set to 1 at the end of the xgets() loop.
  4. .
  5. At the next iteration, fgets will be passed a buffer of length 1, so it
  6. will only be able to read an empty string (the buffer must always have
  7. space for the trailing NUL).
  8. .
  9. strlen(3) on the empty string will return 0, so len will not be modified
  10. anymore and the last step will repeat forever.
  11. .
  12. To reproduce:
  13. perl -e 'print "#sshd: " . ("127.0.0.1, " x 210) . "\n"' > hosts.deny
  14. tcpdmatch -d test localhost
  15. Author: Marco d'Itri <md@linux.it>
  16. Bug-Debian: http://bugs.debian.org/596261
  17. --- a/misc.c
  18. +++ b/misc.c
  19. @@ -45,6 +45,8 @@ FILE *fp;
  20. }
  21. ptr += got;
  22. len -= got;
  23. + if (len == 1)
  24. + return(start);
  25. ptr[0] = 0;
  26. }
  27. return (ptr > start ? start : 0);
  28. --- a/hosts_access.c
  29. +++ b/hosts_access.c
  30. @@ -165,7 +165,9 @@ struct request_info *request;
  31. while (match == NO && xgets(sv_list, sizeof(sv_list), fp) != 0) {
  32. if (sv_list[strlen(sv_list) - 1] != '\n') {
  33. tcpd_warn("missing newline or line too long");
  34. - continue;
  35. + tcpd_warn("all the subsequent rules will be ignored");
  36. + match = ERR;
  37. + break;
  38. }
  39. if (sv_list[0] == '#' || sv_list[strspn(sv_list, " \t\r\n")] == 0)
  40. continue;