700-wcsnrtombs-cve-2020-28928.diff 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c
  2. index 676932b5..95e25e70 100644
  3. --- a/src/multibyte/wcsnrtombs.c
  4. +++ b/src/multibyte/wcsnrtombs.c
  5. @@ -1,41 +1,33 @@
  6. #include <wchar.h>
  7. +#include <limits.h>
  8. +#include <string.h>
  9. size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st)
  10. {
  11. - size_t l, cnt=0, n2;
  12. - char *s, buf[256];
  13. const wchar_t *ws = *wcs;
  14. - const wchar_t *tmp_ws;
  15. -
  16. - if (!dst) s = buf, n = sizeof buf;
  17. - else s = dst;
  18. -
  19. - while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) {
  20. - if (n2>=n) n2=n;
  21. - tmp_ws = ws;
  22. - l = wcsrtombs(s, &ws, n2, 0);
  23. - if (!(l+1)) {
  24. - cnt = l;
  25. - n = 0;
  26. + size_t cnt = 0;
  27. + if (!dst) n=0;
  28. + while (ws && wn) {
  29. + char tmp[MB_LEN_MAX];
  30. + size_t l = wcrtomb(n<MB_LEN_MAX ? tmp : dst, *ws, 0);
  31. + if (l==-1) {
  32. + cnt = -1;
  33. break;
  34. }
  35. - if (s != buf) {
  36. - s += l;
  37. + if (dst) {
  38. + if (n<MB_LEN_MAX) {
  39. + if (l>n) break;
  40. + memcpy(dst, tmp, l);
  41. + }
  42. + dst += l;
  43. n -= l;
  44. }
  45. - wn = ws ? wn - (ws - tmp_ws) : 0;
  46. - cnt += l;
  47. - }
  48. - if (ws) while (n && wn) {
  49. - l = wcrtomb(s, *ws, 0);
  50. - if ((l+1)<=1) {
  51. - if (!l) ws = 0;
  52. - else cnt = l;
  53. + if (!*ws) {
  54. + ws = 0;
  55. break;
  56. }
  57. - ws++; wn--;
  58. - /* safe - this loop runs fewer than sizeof(buf) times */
  59. - s+=l; n-=l;
  60. + ws++;
  61. + wn--;
  62. cnt += l;
  63. }
  64. if (dst) *wcs = ws;