Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.9k stars 540 forks source link

AddressSanitizer: heap-buffer-overflow in Perl_newSVpvn_flags #15887

Open p5pRT opened 7 years ago

p5pRT commented 7 years ago

Migrated from rt.perl.org#130841 (status was 'open')

Searchable as RT130841$

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Information about configuration​:

Distributor ID​: Ubuntu Description​: Ubuntu 16.10 Release​: 16.10 Codename​: yakkety Arch​: x86_64

Best Regards\, Marcin T.

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

perl-heap-buffer-overflow

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

perl​: warning​: Setting locale failed. perl​: warning​: Please check that your locale settings​:   LANGUAGE = (unset)\,   LC_ALL = (unset)\,   LC_CTYPE = "UTF-8"\,   LANG = "en_US.UTF-8"   are supported and installed on your system. perl​: warning​: Falling back to a fallback locale ("en_US.UTF-8"). "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 13. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 14. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 15. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 16. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 17. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 18. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 19. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 20. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 21. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 22. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 23. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 24. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 25. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 26. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 27. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 28. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 29. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 30. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 31. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 32. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 33. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 34. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 35. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 36. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 37. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 38. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 39. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 40. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 41. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 42. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 43. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 44. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 45. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 46. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 47. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 48. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 49. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 50. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 51. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 52. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 53. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 54. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 55. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 56. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 57. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 58. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 59. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 60. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 61. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 62. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 63. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 64. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 65. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 66. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 67. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 68. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 69. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 70. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 71. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 72. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 73. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 74. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 75. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 76. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 77. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 78. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 79. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 80. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 81. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 82. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 83. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 84. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 85. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 86. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 87. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 88. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 89. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 90. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 91. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 92. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 93. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 94. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 95. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 96. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 97. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 98. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 99. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 100. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 101. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 102. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 103. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 104. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 105. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 106. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 107. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 108. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 109. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 110. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 111. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 112. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 113. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 114. "my" variable $package masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 115. '\429' resolved to '\o{42}9' at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 121. Possible attempt to separate words with commas at ../../../../../../run/shm/tmp/samples/14877721982846068966265302151 line 143.

==16877==ERROR​: AddressSanitizer​: heap-buffer-overflow on address 0x62100006f1c8 at pc 0x0000009c22fe bp 0x7ffc46edd6d0 sp 0x7ffc46edd6c8 WRITE of size 8 at 0x62100006f1c8 thread T0

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Information about configuration​:

Distributor ID​: Ubuntu Description​: Ubuntu 16.10 Release​: 16.10 Codename​: yakkety Arch​: x86_64

Best Regards\, Marcin T.

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

perl-heap-buffer-overflow-76d-64a-22f

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

perl​: warning​: Setting locale failed. perl​: warning​: Please check that your locale settings​:   LANGUAGE = (unset)\,   LC_ALL = (unset)\,   LC_CTYPE = "UTF-8"\,   LANG = "en_US.UTF-8"   are supported and installed on your system. perl​: warning​: Falling back to a fallback locale ("en_US.UTF-8"). '\429' resolved to '\o{42}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 18. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 39. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 40. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 41. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 41. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 42. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 42. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 43. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 43. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 44. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 44. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 45. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 45. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 46. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 46. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 47. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 47. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 48. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 48. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 49. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 49. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 50. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 50. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 51. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 51. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 52. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 52. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 53. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 53. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 54. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 54. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 55. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 55. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 56. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 56. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 57. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 57. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 58. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 58. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 59. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 59. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 60. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 60. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 61. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 61. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 62. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 62. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 63. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 63. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 64. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 64. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 65. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 65. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 66. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 66. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 67. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 67. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 68. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 68. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 69. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 69. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 70. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 70. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 71. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 71. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 72. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 72. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 73. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 73. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 74. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 74. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 75. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 75. "my" variable $invalid_chars masks earlier declaration in same scope at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 76. '\129' resolved to '\o{12}9' at ../../../../../../run/shm/tmp/samples/14877648533517173769767396152 line 76.

==10957==ERROR​: AddressSanitizer​: heap-buffer-overflow on address 0x61d000015d38 at pc 0x000000a2676e bp 0x7ffcf7b25770 sp 0x7ffcf7b25768 WRITE of size 8 at 0x61d000015d38 thread T0   #0 0xa2676d in Perl_newSVpvn_flags /home/mtowalski/Fuzzing/Programs/perl-git/sv.c​:9298​:2   #1 0xa5e64a in Perl_sv_vcatpvfn_flags /home/mtowalski/Fuzzing/Programs/perl-git/sv.c​:13014​:20   #2 0xa4f22f in Perl_sv_catpvf /home/mtowalski/Fuzzing/Programs/perl-git/sv.c​:10871​:5   #3 0x86d553 in Perl_mess_sv /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:1436​:17   #4 0x871bcf in Perl_vmess /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:1486​:12   #5 0x871bcf in Perl_vwarn /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:1859   #6 0x8724fb in Perl_vwarner /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:1975​:2   #7 0x872f64 in Perl_warner /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:1951​:5   #8 0x7109e9 in S_pad_check_dup /home/mtowalski/Fuzzing/Programs/perl-git/pad.c​:878​:6   #9 0x7109e9 in Perl_pad_add_name_pvn /home/mtowalski/Fuzzing/Programs/perl-git/pad.c​:601   #10 0x507ca0 in Perl_allocmy /home/mtowalski/Fuzzing/Programs/perl-git/op.c​:676​:11   #11 0x67210c in S_pending_ident /home/mtowalski/Fuzzing/Programs/perl-git/toke.c​:8922​:26   #12 0x67210c in Perl_yylex /home/mtowalski/Fuzzing/Programs/perl-git/toke.c​:4811   #13 0x6fc45a in Perl_yyparse /home/mtowalski/Fuzzing/Programs/perl-git/perly.c​:340​:34   #14 0x5e61fd in S_parse_body /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2377​:9   #15 0x5ddbae in perl_parse /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:1692​:2   #16 0x5031d1 in main /home/mtowalski/Fuzzing/Programs/perl-git/perlmain.c​:121​:18

p5pRT commented 7 years ago

From @hvds

Just updating subject to the function from the stacktrace.

p5pRT commented 7 years ago

From @hvds

On Wed\, 22 Feb 2017 13​:46​:26 -0800\, mtowalski@​pentest.net.pl wrote​:

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Hi Marcin\, it'd be useful to know how you built perl​: I can't reproduce based on my default ASAN build. Please could you supply the output of 'perl -V' for the perl in question?

Also\, it looks as if some of your examples may have been generated with a fuzzer. If so\, and that fuzzer provides a minimizer (such as afl-cmin in the case of afl)\, it's usually more helpful for us to have minimized test cases. I strongly recommend setting PERL_HASH_SEED when fuzzing or minimizing\, to avoid confusing the tools with random behaviour​: see perlrun(1) for details.

Thanks\,

Hugo

p5pRT commented 7 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 7 years ago

From @tonycoz

On Wed\, 22 Feb 2017 12​:36​:31 -0800\, mtowalski@​pentest.net.pl wrote​:

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Information about configuration​:

Distributor ID​: Ubuntu Description​: Ubuntu 16.10 Release​: 16.10 Codename​: yakkety Arch​: x86_64

Best Regards\, Marcin T.

This looks like an allocation size overflow\, at the point of the crash​:

(gdb) p PL_tmps_ix $1 = 537 (gdb) p PL_tmps_max $2 = 1306846015273836496

How do we get that ridiculous value​:

(gdb) watch PL_tmps_max Hardware watchpoint 1​: PL_tmps_max (gdb) condition 1 PL_tmps_max > 10000 (gdb) r Starting program​: /home/tony/dev/perl/git/perl/perl -Ilib ../130839.pl \<\<\<\>>> Hardware watchpoint 1​: PL_tmps_max

Old value = 537 New value = 1306846015273836496 Perl_tmps_grow_p (ix=1306846015273836495) at scope.c​:190 190 Renew(PL_tmps_stack\, PL_tmps_max\, SV*); (gdb) p extend_to $1 = 1306846015273836495 (gdb) bt #0 Perl_tmps_grow_p (ix=1306846015273836495) at scope.c​:190 #1 0x00000000009e12d1 in Perl_pp_flop () at pp_ctl.c​:1228 #2 0x0000000000749474 in Perl_runops_debug () at dump.c​:2450 #3 0x000000000044499f in S_gen_constant_list (o=0x61d000020648) at op.c​:4673 #4 0x000000000042e687 in Perl_list (o=0x61d000020648) at op.c​:2299 #5 0x00000000004941dc in Perl_ck_entersub_args_list (   entersubop=0x61d000020588) at op.c​:11531 #6 0x0000000000499a12 in Perl_ck_subr (o=0x61d000020588) at op.c​:12122 #7 0x0000000000447bed in Perl_newUNOP (type=184\, flags=64\,   first=0x61d000020600) at op.c​:5093 #8 0x000000000060d784 in Perl_yyparse (gramtype=258) at perly.y​:1136 #9 0x00000000004bcc19 in S_parse_body (env=0x0\, xsinit=0x41fdf3 \<xs_init>)   at perl.c​:2377 #10 0x00000000004b89fa in perl_parse (my_perl=0x60200000eff0\,   xsinit=0x41fdf3 \<xs_init>\, argc=3\, argv=0x7fffffffe848\, env=0x0)   at perl.c​:1692 #11 0x000000000041fc74 in main (argc=3\, argv=0x7fffffffe848\,   env=0x7fffffffe868) at perlmain.c​:121 (gdb) p PL_tmps_max * sizeof(SV*) $2 = -7991975951518859648 (gdb)

Which should fail.

Tony

p5pRT commented 7 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 7 years ago

From @tonycoz

On Wed\, 22 Feb 2017 13​:46​:26 -0800\, mtowalski@​pentest.net.pl wrote​:

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Information about configuration​:

Distributor ID​: Ubuntu Description​: Ubuntu 16.10 Release​: 16.10 Codename​: yakkety Arch​: x86_64

Best Regards\, Marcin T.

This fails on​:

(gdb) up 7 #7 0x00000000008f18ea in Perl_newSVpvn_flags (   s=0x60400000d732 "../130841.pl"\, len=12\, flags=524288) at sv.c​:9298 9298 PUSH_EXTEND_MORTAL__SV_C(sv);

and given the code has the same​:

  -1306846015273835958 .. 5

as 130839\, I suspect it's the same base cause.

Tony

p5pRT commented 7 years ago

From @hvds

On Wed\, 22 Feb 2017 16​:41​:18 -0800\, tonyc wrote​:

On Wed\, 22 Feb 2017 13​:46​:26 -0800\, mtowalski@​pentest.net.pl wrote​:

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Information about configuration​:

Distributor ID​: Ubuntu Description​: Ubuntu 16.10 Release​: 16.10 Codename​: yakkety Arch​: x86_64

Best Regards\, Marcin T.

This fails on​:

(gdb) up 7 #7 0x00000000008f18ea in Perl_newSVpvn_flags ( s=0x60400000d732 "../130841.pl"\, len=12\, flags=524288) at sv.c​:9298 9298 PUSH_EXTEND_MORTAL__SV_C(sv);

and given the code has the same​:

-1306846015273835958 .. 5

as 130839\, I suspect it's the same base cause.

I think it is somehow triggered by the number of warnings. I was eventually able to reproduce\, and can reduce it to this​:

% perl -Mbigint -e '$big = "0" + 2 ** 63 - 256; print qq{xx(0 .. $big); } . (qq[my \$z = 1; ] x 24)' | ./perl -Ilib -w

With 23 instead of 24 repetitions I get the expected "Out of memory during array extend at - line 1."; the precise count needed seems to be sensitive to other factors though.

Hugo

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

Hello\,

Iv’e compiled it like this : ./Configure -des -Dusedevel -DDEBUGGING -Dcc=clang -Doptimize=-O2 -Accflags="-fsanitize=address -fsanitize-coverage=edge" -Aldflags="-fsanitize=address -fsanitize-coverage=edge" -Alddlflags=-shared

Next round of fuzzing I will do with Yours suggestions.

Best Regards\, Marcin T.

On 23 Feb 2017\, at 01​:09\, Hugo van der Sanden via RT \perl5\-security\-report@&#8203;perl\.org wrote​:

On Wed\, 22 Feb 2017 13​:46​:26 -0800\, mtowalski@​pentest.net.pl wrote​:

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Hi Marcin\, it'd be useful to know how you built perl​: I can't reproduce based on my default ASAN build. Please could you supply the output of 'perl -V' for the perl in question?

Also\, it looks as if some of your examples may have been generated with a fuzzer. If so\, and that fuzzer provides a minimizer (such as afl-cmin in the case of afl)\, it's usually more helpful for us to have minimized test cases. I strongly recommend setting PERL_HASH_SEED when fuzzing or minimizing\, to avoid confusing the tools with random behaviour​: see perlrun(1) for details.

Thanks\,

Hugo

p5pRT commented 7 years ago

From @hvds

Ah\, with the reduced version I can run it with miniperl. -Dl output pointed to corruption of the savestack\, which turned out to be overrun from the tmps stack (as Tony found in [perl #130839])\, which turns out to be as follows​:

In pp_flop() we carefully check that n\, the number of items we want to push onto the tmps stack\, has not overflowed to something invalid. If it's ok\, we then call EXTEND_MORTAL(n). However that macro wants to increase the size to (PL_tmps_ix + n)\, and the macro does not protect against overflow from that further addition.

I tried the simplistic​: --- a/pp.h +++ b/pp.h @​@​ -513\,6 +513\,10 @​@​ Does not use C\. See also C\<L\>\, C\<L\> and C\<L\>. #define EXTEND_MORTAL(n) \   STMT_START { \   SSize_t eMiX = PL_tmps_ix + (n); \ +if (eMiX \< PL_tmps_ix) { \ + /* overflow or other error */ \ + Perl_croak(aTHX_ "panic​: invalid size for tmps stack"); \ +} \   if (UNLIKELY(eMiX >= PL_tmps_max)) \   (void)Perl_tmps_grow_p(aTHX_ eMiX); \   } STMT_END

.. but that didn't fix it. I do think that's the place for it\, though\, even if we also want an additional explicit check in pp_flop to be able to give a better error message.

I'll merge this with 130839 now.

Hugo

p5pRT commented 7 years ago

From @hvds

On Thu\, 23 Feb 2017 04​:29​:11 -0800\, hv wrote​:

[...] which turns out to be as follows​:

In pp_flop() we carefully check that n\, the number of items we want to push onto the tmps stack\, has not overflowed to something invalid. If it's ok\, we then call EXTEND_MORTAL(n). However that macro wants to increase the size to (PL_tmps_ix + n)\, and the macro does not protect against overflow from that further addition.

It's not that\, though that may also be a problem.

In this case we're not actually overflowing in that addition\, but proceeding to hit the wraparound check in Renew()\, spotting the overflow and calling croak_memory_wrap(). However by that point we've already updated PL_tmps_max as if the Renew() were going to succeed\, and hilarity ensues.

I think the below is the immediate fix\, not sure if we need to change EXTEND_MORTAL as well\, and I'm not sure if the two manipulations of extend_to visible in the diff context also need extra checks.

And I can't tell right now if this is exploitable.

Hugo --- a/scope.c +++ b/scope.c @​@​ -186\,8 +186\,8 @​@​ Perl_tmps_grow_p(pTHX_ SSize_t ix)   if (ix - PL_tmps_max \< 128)   extend_to += (PL_tmps_max \< 512) ? 128 : 512; #endif + Renew(PL_tmps_stack\, extend_to + 1\, SV*);   PL_tmps_max = extend_to + 1; - Renew(PL_tmps_stack\, PL_tmps_max\, SV*);   return ix; }

p5pRT commented 7 years ago

From @hvds

On Thu\, 23 Feb 2017 06​:31​:34 -0800\, hv wrote​:

In this case we're [...] proceeding to hit the wraparound check in Renew()\, spotting the overflow and calling croak_memory_wrap(). However by that point we've already updated PL_tmps_max as if the Renew() were going to succeed\, and hilarity ensues.

I did a quick crude audit (below) for similar cases by grepping for Renew and then attempting to check for each case whether the new length passed to Renew came from something that might still be visible after a longjmp. I found quite a few cases.

My current inclination is that it would be hard to rule out exploitability for the pp_flop case - at least\, I'm confident that there will be perfectly reasonable-looking code out there using tainted range-ends. Ruling it out for the general case will likely be harder still.

It's possible that many of these cannot wraparound (either absolutely or practically)\, but I didn't attempt to think about that for this pass - I'm not sure if wraparound is the only failure mode that could cause us to hit a croak path that then attempt to continue doing stuff. If it is\, then making that path more immediately fatal might be the easiest next step.

In any case\, I'm going to stop there and wait for some feedback from others.

Hugo

  Perl_my_cxt_init stores PL_my_cxt_size #ifndef PERL_GLOBAL_STRUCT_PRIVATE util.c​:5357​: Renew(PL_my_cxt_list\, PL_my_cxt_size\, void *); #else util.c​:5420​: Renew(PL_my_cxt_list\, PL_my_cxt_size\, void *); util.c​:5421​: Renew(PL_my_cxt_keys\, PL_my_cxt_size\, const char *); #endif

  Perl_reentrant_retry stores many fields in PL_reentrant_buffer (comes from/also in regen/reentr.pl) reentr.c​:330​: Renew(PL_reentrant_buffer->_hostent_buffer\, reentr.c​:363​: Renew(PL_reentrant_buffer->_grent_buffer\, reentr.c​:398​: Renew(PL_reentrant_buffer->_netent_buffer\, reentr.c​:430​: Renew(PL_reentrant_buffer->_pwent_buffer\, reentr.c​:466​: Renew(PL_reentrant_buffer->_protoent_buffer\, reentr.c​:496​: Renew(PL_reentrant_buffer->_servent_buffer\,

  pp_entersub stores AvMAX(av) pp_hot.c​:4138​: Renew(ary\, items\, SV*);

  PerlIO_list_push stores list->len perlio.c​:552​: Renew(list->array\, list->len\, PerlIO_pair_t);

  S_sortcv_stacked sets AvMAX(av) = 1 pp_sort.c​:1835​: Renew(ary\,2\,SV*);

  yylex​: I think these are never stored\, probably ok (but churny) toke.c​:4801​: Renew(PL_lex_brackstack\, PL_lex_brackets + 10\, char); toke.c​:4877​: Renew(PL_lex_casestack\, PL_lex_casemods + 2\, char); toke.c​:5806​: Renew(PL_lex_brackstack\, PL_lex_brackets + 10\, char); toke.c​:6052​: Renew(PL_lex_brackstack\, PL_lex_brackets + 10\, char); toke.c​:11982​: Renew(PL_lex_brackstack\, PL_lex_brackets + 10\, char);

  Perl_cxinc stores cxstack_max scope.c​:94​: Renew(cxstack\, cxstack_max + 1\, PERL_CONTEXT);   Perl_push_scope stores PL_scopestack_max scope.c​:106​: Renew(PL_scopestack\, PL_scopestack_max\, I32); scope.c​:108​: Renew(PL_scopestack_name\, PL_scopestack_max\, const char*);   Perl_savestack_grow stores PL_savestack_max scope.c​:150​: Renew(PL_savestack\, PL_savestack_max + SS_MAXPUSH\, ANY);   Perl_savestack_grow_cnt stores PL_savestack_max scope.c​:159​: Renew(PL_savestack\, PL_savestack_max + SS_MAXPUSH\, ANY);   Perl_tmps_grow_p stores PL_tmps_max scope.c​:189​: Renew(PL_tmps_stack\, extend_to + 1\, SV*);

  macro TRIE_LIST_PUSH stores TRIE_LIST_LEN( state ) regcomp.c​:2359​: Renew( trie->states[ state ].trans.list\, ging\, reg_trie_trans_le );   S_concat_pat stores pRExC_state->code_blocks->count regcomp.c​:6420​: Renew(pRExC_state->code_blocks->cb\,

  Perl_hv_ename_add stores aux->xhv_name_count hv.c​:2427​: Renew(aux->xhv_name_u.xhvnameu_names\, count + 1\, HEK *);

  macro DEFER_OP stores defer_stack_alloc\, but that's local (in multiple functions)\, probably ok op.c​:184​: Renew(defer_stack\, defer_stack_alloc\, OP *);

  pthread_startit stores thread_join_count os2/os2.c​:360​: Renew(thread_join_data\, thread_join_count\, thread_join_t);

  my_cxinc stores cxstack_max (dup of scope.c​:Perl_cxinc) cpan/Scalar-List-Utils/ListUtil.xs​:41​: Renew(cxstack\, cxstack_max + 1\, struct context);

  win32_readdir stores dirp->size win32/win32.c​:972​: Renew(dirp->start\, dirp->size\, char); win32/wince.c​:769​: Renew(dirp->start\, dirp->size\, char);

  macro Renew_d_if_not_enough_to stores dlen\, but that's local (in multiple functions)\, probably ok dist/Unicode-Normalize/Normalize.xs​:70​: Renew(dstart\, dlen+1\, U8); \

p5pRT commented 7 years ago

From @iabyn

On Fri\, Feb 24\, 2017 at 03​:39​:31AM -0800\, Hugo van der Sanden via RT wrote​:

On Thu\, 23 Feb 2017 06​:31​:34 -0800\, hv wrote​:

In this case we're [...] proceeding to hit the wraparound check in Renew()\, spotting the overflow and calling croak_memory_wrap(). However by that point we've already updated PL_tmps_max as if the Renew() were going to succeed\, and hilarity ensues.

I did a quick crude audit (below) for similar cases by grepping for Renew and then attempting to check for each case whether the new length passed to Renew came from something that might still be visible after a longjmp. I found quite a few cases.

My current inclination is that it would be hard to rule out exploitability for the pp_flop case - at least\, I'm confident that there will be perfectly reasonable-looking code out there using tainted range-ends. Ruling it out for the general case will likely be harder still.

For ones (such as pp_flop) that involve accidentally setting PL_tmps_max to a huge value\, I don't actually see it as much of a risk. Let me explain...

The sample code involves the constant-folding of (0..huge_const_value)\, which it does with an eval implicitly wrapped round it. Realistic code which allows the attacker to control the upper bound would have to be a run-time flop that happens to be wrapped in an eval or require\, e.g.

  eval {   my @​range = 1..$attacker_controlled_huge_number;   ...   }

Note that code like this is already susceptible to a DoS attack\, since the attacker can make the perl process malloc as much memory as they want.

On return from the eval\, any attempt to push SVs on the tmps stack beyond what it's already been grown to will write SV pointers beyond the stack\, overwriting other stuff. There is a good chance however that the code has already reached the high-water mark in tmps stack allocation\, and never needs to grow further (crashing out from the eval/require block is likely to free up tmps stack slots).

Even if the code does write beyond the end of the tmps stack\, this is likely to just cause a crash (and remember such code is already vulnerable to a DoS attack anyway); an exploit can only overwrite with the addresses of recently allocated SVs rather than arbitrary code or data.

Overall this feels more like several other 32/64 or wraparound allocation issues we've had in the past\, where we've fixed it but haven't treated it as a security issue. The main exception to this was the (' ' x $large_int) issue\, which by tickling 32/64-bit issues present in both perl *and* glibc\, could have involved treating a random area of memory as the jump table of memset(). For that we released 5.14.4 (IIRC).

It's possible that many of these cannot wraparound (either absolutely or practically)\, but I didn't attempt to think about that for this pass - I'm not sure if wraparound is the only failure mode that could cause us to hit a croak path that then attempt to continue doing stuff. If it is\, then making that path more immediately fatal might be the easiest next step.

I haven't looked closely at your other Renew() examples yet.

In any case\, I'm going to stop there and wait for some feedback from others.

Regardless of what we end up deciding security-issue wise\, should I provide fixes or leave that to you? (I am happy to work on this). I think the fixes should go in 5.26.0.

-- Any [programming] language that doesn't occasionally surprise the novice will pay for it by continually surprising the expert.   -- Larry Wall

p5pRT commented 7 years ago

From @hvds

On Tue\, 28 Feb 2017 06​:34​:57 -0800\, davem wrote​:

In any case\, I'm going to stop there and wait for some feedback from others.

Regardless of what we end up deciding security-issue wise\, should I provide fixes or leave that to you? (I am happy to work on this). I think the fixes should go in 5.26.0.

I did start working a bit more on it today\, covering all the Renew() cases annotated in my previous message except for hv.c​:Perl_hv_ename_add()\, which needs a bit more effort.

Attached is the first pass at those\, I need to go back through to make sure I haven't messed up (but it passes a basic 'make test').

I've made the assumption that retaining existing "catchable die" semantics is necessary; it's open for debate whether that's correct.

I think it's also worth discussing whether we should go further. Most of these pathways involve additional calculations that can wrap\, without taking appropriate steps. I'd have loved to provide some new macros that could have moved more of the logic into a separate place (eg a "Renew and update my size in the right order" macro)\, but sadly I found so little regularity there seemed little I could do there.

I'd love to at least standardize on types\, and provide for all those a minimum set of functions such as memsafe_add_size_t\, memsafe_mul_ssize_t\, etc. (I had a think about type-agnostic macros\, but I believe they'd need to know MAX_FOR_MY_TYPE and signedness\, and could see no way to provide those in the general case.)

I'll look more at your analysis; I already answered my first two objections while writing this. :)

Hugo

p5pRT commented 7 years ago

From @hvds

0001-OS2-update-size-after-Renew.patch ```diff From 8f22df04fab6799d7797d5339816169544e6036e Mon Sep 17 00:00:00 2001 From: Hugo van der Sanden Date: Tue, 28 Feb 2017 11:19:54 +0000 Subject: [PATCH 1/5] OS2: update size after Renew Setting it before Renew can cause problems if the Renew fails. --- os2/os2.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/os2/os2.c b/os2/os2.c index d7a4b58..7ce3b70 100644 --- a/os2/os2.c +++ b/os2/os2.c @@ -354,14 +354,15 @@ pthread_startit(void *arg1) PERL_SET_CONTEXT(0); if (tid >= thread_join_count) { int oc = thread_join_count; + int new_count = tid + 5 + tid/5; - thread_join_count = tid + 5 + tid/5; if (thread_join_data) { - Renew(thread_join_data, thread_join_count, thread_join_t); - Zero(thread_join_data + oc, thread_join_count - oc, thread_join_t); + Renew(thread_join_data, new_count, thread_join_t); + Zero(thread_join_data + oc, new_count - oc, thread_join_t); } else { - Newxz(thread_join_data, thread_join_count, thread_join_t); + Newxz(thread_join_data, new_count, thread_join_t); } + thread_join_count = new_count; } if (thread_join_data[tid].state != pthreads_st_none) { /* Can't croak, the setjmp() is not in scope... */ -- 2.10.2 ```
p5pRT commented 7 years ago

From @hvds

0002-WIN32-update-size-after-Renew.patch ```diff From ff173d2d40c972c0ceb57c253204f83c5233481a Mon Sep 17 00:00:00 2001 From: Hugo van der Sanden Date: Tue, 28 Feb 2017 11:21:09 +0000 Subject: [PATCH 2/5] WIN32: update size after Renew Setting it before Renew can cause problems if the Renew fails. --- win32/win32.c | 2 +- win32/wince.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/win32/win32.c b/win32/win32.c index 3981921..2e82c53 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -968,8 +968,8 @@ win32_readdir(DIR *dirp) * new name and its null terminator */ while (newsize > dirp->size) { long curpos = dirp->curr - dirp->start; + Renew(dirp->start, dirp->size * 2, char); dirp->size *= 2; - Renew(dirp->start, dirp->size, char); dirp->curr = dirp->start + curpos; } strcpy(dirp->start + endpos, buffer); diff --git a/win32/wince.c b/win32/wince.c index 56a23b5..0458537 100644 --- a/win32/wince.c +++ b/win32/wince.c @@ -765,8 +765,8 @@ win32_readdir(DIR *dirp) * new name and its null terminator */ while (newsize > dirp->size) { long curpos = dirp->curr - dirp->start; + Renew(dirp->start, dirp->size * 2, char); dirp->size *= 2; - Renew(dirp->start, dirp->size, char); dirp->curr = dirp->start + curpos; } strcpy(dirp->start + endpos, ptr); -- 2.10.2 ```
p5pRT commented 7 years ago

From @hvds

0003-reentr-update-size-after-Renew.patch ```diff From 593eaf30d4ef1c96c57c22da35572ac55852cc9d Mon Sep 17 00:00:00 2001 From: Hugo van der Sanden Date: Tue, 28 Feb 2017 11:21:55 +0000 Subject: [PATCH 3/5] reentr: update size after Renew Setting it before Renew can cause problems if the Renew fails. Required 'make regen'. --- reentr.c | 37 +++++++++++++++++++------------------ regen/reentr.pl | 37 +++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/reentr.c b/reentr.c index c464acc..fdd1e80 100644 --- a/reentr.c +++ b/reentr.c @@ -33,6 +33,13 @@ #include "perl.h" #include "reentr.h" +#define RenewDouble(data_pointer, size_pointer, type) \ + STMT_START { \ + const size_t size = *(size_pointer) * 2; \ + Renew((data_pointer), (size), (type)); \ + *(size_pointer) = size; \ + } + void Perl_reentrant_size(pTHX) { PERL_UNUSED_CONTEXT; @@ -326,9 +333,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_hostent_size *= 2; - Renew(PL_reentrant_buffer->_hostent_buffer, - PL_reentrant_buffer->_hostent_size, char); + RenewDouble(PL_reentrant_buffer->_hostent_buffer, + &PL_reentrant_buffer-_hostent_size, char); switch (PL_op->op_type) { case OP_GHBYADDR: p0 = va_arg(ap, void *); @@ -359,9 +365,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Gid_t gid; - PL_reentrant_buffer->_grent_size *= 2; - Renew(PL_reentrant_buffer->_grent_buffer, - PL_reentrant_buffer->_grent_size, char); + RenewDouble(PL_reentrant_buffer->_grent_buffer, + &PL_reentrant_buffer->_grent_size, char); switch (PL_op->op_type) { case OP_GGRNAM: p0 = va_arg(ap, void *); @@ -394,9 +399,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Netdb_net_t net; - PL_reentrant_buffer->_netent_size *= 2; - Renew(PL_reentrant_buffer->_netent_buffer, - PL_reentrant_buffer->_netent_size, char); + RenewDouble(PL_reentrant_buffer->_netent_buffer, + &PL_reentrant_buffer->_netent_size, char); switch (PL_op->op_type) { case OP_GNBYADDR: net = va_arg(ap, Netdb_net_t); @@ -426,9 +430,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Uid_t uid; - PL_reentrant_buffer->_pwent_size *= 2; - Renew(PL_reentrant_buffer->_pwent_buffer, - PL_reentrant_buffer->_pwent_size, char); + RenewDouble(PL_reentrant_buffer->_pwent_buffer, + &PL_reentrant_buffer->_pwent_size, char); switch (PL_op->op_type) { case OP_GPWNAM: p0 = va_arg(ap, void *); @@ -462,9 +465,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_protoent_size *= 2; - Renew(PL_reentrant_buffer->_protoent_buffer, - PL_reentrant_buffer->_protoent_size, char); + RenewDouble(PL_reentrant_buffer->_protoent_buffer, + &PL_reentrant_buffer->_protoent_size, char); switch (PL_op->op_type) { case OP_GPBYNAME: p0 = va_arg(ap, void *); @@ -492,9 +494,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_servent_size *= 2; - Renew(PL_reentrant_buffer->_servent_buffer, - PL_reentrant_buffer->_servent_size, char); + RenewDouble(PL_reentrant_buffer->_servent_buffer, + &PL_reentrant_buffer->_servent_size, char); switch (PL_op->op_type) { case OP_GSBYNAME: p0 = va_arg(ap, void *); diff --git a/regen/reentr.pl b/regen/reentr.pl index 802b8db..bd8ad10 100644 --- a/regen/reentr.pl +++ b/regen/reentr.pl @@ -773,6 +773,13 @@ print $c <<"EOF"; #include "perl.h" #include "reentr.h" +#define RenewDouble(data_pointer, size_pointer, type) \\ + STMT_START { \\ + const size_t size = *(size_pointer) * 2; \\ + Renew((data_pointer), (size), (type)); \\ + *(size_pointer) = size; \\ + } + void Perl_reentrant_size(pTHX) { PERL_UNUSED_CONTEXT; @@ -840,9 +847,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_hostent_size *= 2; - Renew(PL_reentrant_buffer->_hostent_buffer, - PL_reentrant_buffer->_hostent_size, char); + RenewDouble(PL_reentrant_buffer->_hostent_buffer, + &PL_reentrant_buffer-_hostent_size, char); switch (PL_op->op_type) { case OP_GHBYADDR: p0 = va_arg(ap, void *); @@ -873,9 +879,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Gid_t gid; - PL_reentrant_buffer->_grent_size *= 2; - Renew(PL_reentrant_buffer->_grent_buffer, - PL_reentrant_buffer->_grent_size, char); + RenewDouble(PL_reentrant_buffer->_grent_buffer, + &PL_reentrant_buffer->_grent_size, char); switch (PL_op->op_type) { case OP_GGRNAM: p0 = va_arg(ap, void *); @@ -908,9 +913,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Netdb_net_t net; - PL_reentrant_buffer->_netent_size *= 2; - Renew(PL_reentrant_buffer->_netent_buffer, - PL_reentrant_buffer->_netent_size, char); + RenewDouble(PL_reentrant_buffer->_netent_buffer, + &PL_reentrant_buffer->_netent_size, char); switch (PL_op->op_type) { case OP_GNBYADDR: net = va_arg(ap, Netdb_net_t); @@ -940,9 +944,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Uid_t uid; - PL_reentrant_buffer->_pwent_size *= 2; - Renew(PL_reentrant_buffer->_pwent_buffer, - PL_reentrant_buffer->_pwent_size, char); + RenewDouble(PL_reentrant_buffer->_pwent_buffer, + &PL_reentrant_buffer->_pwent_size, char); switch (PL_op->op_type) { case OP_GPWNAM: p0 = va_arg(ap, void *); @@ -976,9 +979,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_protoent_size *= 2; - Renew(PL_reentrant_buffer->_protoent_buffer, - PL_reentrant_buffer->_protoent_size, char); + RenewDouble(PL_reentrant_buffer->_protoent_buffer, + &PL_reentrant_buffer->_protoent_size, char); switch (PL_op->op_type) { case OP_GPBYNAME: p0 = va_arg(ap, void *); @@ -1006,9 +1008,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_servent_size *= 2; - Renew(PL_reentrant_buffer->_servent_buffer, - PL_reentrant_buffer->_servent_size, char); + RenewDouble(PL_reentrant_buffer->_servent_buffer, + &PL_reentrant_buffer->_servent_size, char); switch (PL_op->op_type) { case OP_GSBYNAME: p0 = va_arg(ap, void *); -- 2.10.2 ```
p5pRT commented 7 years ago

From @hvds

0004-update-size-after-Renew.patch ```diff From 840020e25f40c2ddc7d04a61df6455746a80a997 Mon Sep 17 00:00:00 2001 From: Hugo van der Sanden Date: Tue, 28 Feb 2017 11:23:09 +0000 Subject: [PATCH 4/5] update size after Renew Setting it before Renew can cause problems if the Renew fails. --- perlio.c | 7 ++++--- pp_hot.c | 2 +- pp_sort.c | 2 +- regcomp.c | 10 ++++++---- scope.c | 29 +++++++++++++++++------------ util.c | 18 +++++++++++------- 6 files changed, 40 insertions(+), 28 deletions(-) diff --git a/perlio.c b/perlio.c index 3e936a2..e9d3700 100644 --- a/perlio.c +++ b/perlio.c @@ -547,11 +547,12 @@ PerlIO_list_push(pTHX_ PerlIO_list_t *list, PerlIO_funcs *funcs, SV *arg) PERL_UNUSED_CONTEXT; if (list->cur >= list->len) { - list->len += 8; + const IV new_len = list->len + 8; if (list->array) - Renew(list->array, list->len, PerlIO_pair_t); + Renew(list->array, new_len, PerlIO_pair_t); else - Newx(list->array, list->len, PerlIO_pair_t); + Newx(list->array, new_len, PerlIO_pair_t); + list->len = new_len; } p = &(list->array[list->cur++]); p->funcs = funcs; diff --git a/pp_hot.c b/pp_hot.c index 58bbe2f..4f0d094 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -4134,8 +4134,8 @@ PP(pp_entersub) items = SP - MARK; if (UNLIKELY(items - 1 > AvMAX(av))) { SV **ary = AvALLOC(av); - AvMAX(av) = items - 1; Renew(ary, items, SV*); + AvMAX(av) = items - 1; AvALLOC(av) = ary; AvARRAY(av) = ary; } diff --git a/pp_sort.c b/pp_sort.c index 21e4574..a54768a 100644 --- a/pp_sort.c +++ b/pp_sort.c @@ -1831,8 +1831,8 @@ S_sortcv_stacked(pTHX_ SV *const a, SV *const b) AvARRAY(av) = ary; } if (AvMAX(av) < 1) { - AvMAX(av) = 1; Renew(ary,2,SV*); + AvMAX(av) = 1; AvARRAY(av) = ary; AvALLOC(av) = ary; } diff --git a/regcomp.c b/regcomp.c index 0a80ced..810c457 100644 --- a/regcomp.c +++ b/regcomp.c @@ -2355,8 +2355,9 @@ is the recommended Unicode-aware way of saying #define TRIE_LIST_PUSH(state,fid,ns) STMT_START { \ if ( TRIE_LIST_CUR( state ) >=TRIE_LIST_LEN( state ) ) { \ - U32 ging = TRIE_LIST_LEN( state ) *= 2; \ + U32 ging = TRIE_LIST_LEN( state ) * 2; \ Renew( trie->states[ state ].trans.list, ging, reg_trie_trans_le ); \ + TRIE_LIST_LEN( state ) = ging; \ } \ TRIE_LIST_ITEM( state, TRIE_LIST_CUR( state ) ).forid = fid; \ TRIE_LIST_ITEM( state, TRIE_LIST_CUR( state ) ).newstate = ns; \ @@ -6416,10 +6417,11 @@ S_concat_pat(pTHX_ RExC_state_t * const pRExC_state, * different closure than last time */ *recompile_p = 1; if (pRExC_state->code_blocks) { - pRExC_state->code_blocks->count += ri->code_blocks->count; + int new_count = pRExC_state->code_blocks->count + + ri->code_blocks->count; Renew(pRExC_state->code_blocks->cb, - pRExC_state->code_blocks->count, - struct reg_code_block); + new_count, struct reg_code_block); + pRExC_state->code_blocks->count = new_count; } else pRExC_state->code_blocks = S_alloc_code_blocks(aTHX_ diff --git a/scope.c b/scope.c index 4b302e7..c51a125 100644 --- a/scope.c +++ b/scope.c @@ -90,11 +90,12 @@ I32 Perl_cxinc(pTHX) { const IV old_max = cxstack_max; - cxstack_max = GROW(cxstack_max); - Renew(cxstack, cxstack_max + 1, PERL_CONTEXT); + const IV new_max = GROW(cxstack_max); + Renew(cxstack, new_max + 1, PERL_CONTEXT); + cxstack_max = new_max; /* Without any kind of initialising deep enough recursion * will end up reading uninitialised PERL_CONTEXTs. */ - PoisonNew(cxstack + old_max + 1, cxstack_max - old_max, PERL_CONTEXT); + PoisonNew(cxstack + old_max + 1, new_max - old_max, PERL_CONTEXT); return cxstack_ix + 1; } @@ -102,11 +103,12 @@ void Perl_push_scope(pTHX) { if (UNLIKELY(PL_scopestack_ix == PL_scopestack_max)) { - PL_scopestack_max = GROW(PL_scopestack_max); - Renew(PL_scopestack, PL_scopestack_max, I32); + const IV new_max = GROW(PL_scopestack_max); + Renew(PL_scopestack, new_max, I32); #ifdef DEBUGGING - Renew(PL_scopestack_name, PL_scopestack_max, const char*); + Renew(PL_scopestack_name, new_max, const char*); #endif + PL_scopestack_max = new_max; } #ifdef DEBUGGING PL_scopestack_name[PL_scopestack_ix] = "unknown"; @@ -140,23 +142,26 @@ Perl_markstack_grow(pTHX) void Perl_savestack_grow(pTHX) { + IV new_max; #ifdef STRESS_REALLOC - PL_savestack_max += SS_MAXPUSH; + new_max = PL_savestack_max + SS_MAXPUSH; #else - PL_savestack_max = GROW(PL_savestack_max); + new_max = GROW(PL_savestack_max); #endif /* Note that we allocate SS_MAXPUSH slots higher than ss_max * so that SS_ADD_END(), SSGROW() etc can do a simper check */ - Renew(PL_savestack, PL_savestack_max + SS_MAXPUSH, ANY); + Renew(PL_savestack, new_max + SS_MAXPUSH, ANY); + PL_savestack_max = new_max; } void Perl_savestack_grow_cnt(pTHX_ I32 need) { - PL_savestack_max = PL_savestack_ix + need; + const IV new_max = PL_savestack_ix + need; /* Note that we allocate SS_MAXPUSH slots higher than ss_max * so that SS_ADD_END(), SSGROW() etc can do a simper check */ - Renew(PL_savestack, PL_savestack_max + SS_MAXPUSH, ANY); + Renew(PL_savestack, new_max + SS_MAXPUSH, ANY); + PL_savestack_max = new_max; } #undef GROW @@ -186,8 +191,8 @@ Perl_tmps_grow_p(pTHX_ SSize_t ix) if (ix - PL_tmps_max < 128) extend_to += (PL_tmps_max < 512) ? 128 : 512; #endif + Renew(PL_tmps_stack, extend_to + 1, SV*); PL_tmps_max = extend_to + 1; - Renew(PL_tmps_stack, PL_tmps_max, SV*); return ix; } diff --git a/util.c b/util.c index bd568bc..b324af4 100644 --- a/util.c +++ b/util.c @@ -5352,9 +5352,11 @@ Perl_my_cxt_init(pTHX_ int *index, size_t size) /* make sure the array is big enough */ if (PL_my_cxt_size <= *index) { if (PL_my_cxt_size) { - while (PL_my_cxt_size <= *index) - PL_my_cxt_size *= 2; - Renew(PL_my_cxt_list, PL_my_cxt_size, void *); + IV new_size = PL_my_cxt_size; + while (new_size <= *index) + new_size *= 2; + Renew(PL_my_cxt_list, new_size, void *); + PL_my_cxt_size = new_size; } else { PL_my_cxt_size = 16; @@ -5415,10 +5417,12 @@ Perl_my_cxt_init(pTHX_ const char *my_cxt_key, size_t size) int old_size = PL_my_cxt_size; int i; if (PL_my_cxt_size) { - while (PL_my_cxt_size <= index) - PL_my_cxt_size *= 2; - Renew(PL_my_cxt_list, PL_my_cxt_size, void *); - Renew(PL_my_cxt_keys, PL_my_cxt_size, const char *); + IV new_size = PL_my_cxt_size; + while (new_size <= index) + new_size *= 2; + Renew(PL_my_cxt_list, new_size, void *); + Renew(PL_my_cxt_keys, new_size, const char *); + PL_my_cxt_size = new_size; } else { PL_my_cxt_size = 16; -- 2.10.2 ```
p5pRT commented 7 years ago

From @hvds

0005-Scalar-List-Utils-update-size-after-Renew.patch ```diff From 8e64e17ce84b04640711f771b78df69c411325de Mon Sep 17 00:00:00 2001 From: Hugo van der Sanden Date: Tue, 28 Feb 2017 12:03:56 +0000 Subject: [PATCH 5/5] Scalar-List-Utils: update size after Renew Setting it before Renew can cause problems if the Renew fails. --- cpan/Scalar-List-Utils/ListUtil.xs | 5 +++-- cpan/Scalar-List-Utils/lib/List/Util.pm | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cpan/Scalar-List-Utils/ListUtil.xs b/cpan/Scalar-List-Utils/ListUtil.xs index 79e74d9..06d9df0 100644 --- a/cpan/Scalar-List-Utils/ListUtil.xs +++ b/cpan/Scalar-List-Utils/ListUtil.xs @@ -37,8 +37,9 @@ static I32 my_cxinc(pTHX) { - cxstack_max = cxstack_max * 3 / 2; - Renew(cxstack, cxstack_max + 1, struct context); /* fencepost bug in older CXINC macros requires +1 here */ + const I32 new_max = cxstack_max * 3 / 2; + Renew(cxstack, new_max + 1, struct context); /* fencepost bug in older CXINC macros requires +1 here */ + cxstack_max = new_max; return cxstack_ix + 1; } #endif diff --git a/cpan/Scalar-List-Utils/lib/List/Util.pm b/cpan/Scalar-List-Utils/lib/List/Util.pm index 23473fc..bef6144 100644 --- a/cpan/Scalar-List-Utils/lib/List/Util.pm +++ b/cpan/Scalar-List-Utils/lib/List/Util.pm @@ -15,7 +15,7 @@ our @EXPORT_OK = qw( all any first min max minstr maxstr none notall product reduce sum sum0 shuffle uniq uniqnum uniqstr pairs unpairs pairkeys pairvalues pairmap pairgrep pairfirst ); -our $VERSION = "1.46_02"; +our $VERSION = "1.46_03"; our $XS_VERSION = $VERSION; $VERSION = eval $VERSION; -- 2.10.2 ```
p5pRT commented 7 years ago

From @hvds

On Tue\, 28 Feb 2017 10​:01​:47 -0800\, hv wrote​:

I did start working a bit more on it today\, covering all the Renew() cases annotated in my previous message except for hv.c​:Perl_hv_ename_add()\, which needs a bit more effort.

Attached that additional piece\, as well as a fixup for porting/customized.

Hugo

p5pRT commented 7 years ago

From @hvds

0001-Scalar-List-Utils-fixup.patch ```diff diff --git a/t/porting/customized.dat b/t/porting/customized.dat index c73daf2..edbc117 100644 --- a/t/porting/customized.dat +++ b/t/porting/customized.dat @@ -47,7 +47,7 @@ Pod::Checker cpan/Pod-Checker/t/pod/contains_bad_pod.xr 73538fd80dfe6e19ad561fe0 Pod::Checker cpan/Pod-Checker/t/pod/selfcheck.t 8ce3cfd38e4b9bcf5bc7fe7f2a14195e49aed7d8 Pod::Checker cpan/Pod-Checker/t/pod/testcmp.pl a0cd5c8eca775c7753f4464eee96fa916e3d8a16 Pod::Checker cpan/Pod-Checker/t/pod/testpchk.pl b2072c7f4379fd050e15424175d7cac5facf5b3b -Scalar-List-Utils cpan/Scalar-List-Utils/lib/List/Util.pm 8cbd3463af838b4a39a7077bea3fe758a71f8ec3 +Scalar-List-Utils cpan/Scalar-List-Utils/lib/List/Util.pm d0fe547422e4f6434d2c8c141468457071317f36 Scalar-List-Utils cpan/Scalar-List-Utils/lib/List/Util/XS.pm 2d09b84a5575e67834655a0e9b3569c83d9a3902 Scalar-List-Utils cpan/Scalar-List-Utils/lib/Scalar/Util.pm 98af8fe390d9c9fa11a1fafebbc68ea663cdce2c Scalar-List-Utils cpan/Scalar-List-Utils/lib/Sub/Util.pm 188cf0dd95cd7ba60fd6a366f440811fb52c2c79 ```
p5pRT commented 7 years ago

From @hvds

0002-Perl_hv_ename_add-update-size-after-Renew.patch ```diff From 7fa3de06541e91a79f74048b111b0e8357fc80f0 Mon Sep 17 00:00:00 2001 From: Hugo van der Sanden Date: Wed, 1 Mar 2017 13:57:08 +0000 Subject: [PATCH 2/2] Perl_hv_ename_add: update size after Renew Setting it before Renew can cause problems if the Renew fails. --- hv.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hv.c b/hv.c index efeadb7..b01a50c 100644 --- a/hv.c +++ b/hv.c @@ -2407,10 +2407,10 @@ Perl_hv_ename_add(pTHX_ HV *hv, const char *name, U32 len, U32 flags) if (aux->xhv_name_count) { I32 count = aux->xhv_name_count; + I32 new_count; HEK ** const xhv_name = aux->xhv_name_u.xhvnameu_names + (count<0); HEK **hekp = xhv_name + (count < 0 ? -count - 1 : count); - while (hekp-- > xhv_name) - { + while (hekp-- > xhv_name) { assert(*hekp); if ( (HEK_UTF8(*hekp) || (flags & SVf_UTF8)) @@ -2422,9 +2422,14 @@ Perl_hv_ename_add(pTHX_ HV *hv, const char *name, U32 len, U32 flags) return; } } - if (count < 0) aux->xhv_name_count--, count = -count; - else aux->xhv_name_count++; + if (count < 0) { + new_count = aux->xhv_name_count - 1; + count = -count; + } else { + new_count = aux->xhv_name_count + 1; + } Renew(aux->xhv_name_u.xhvnameu_names, count + 1, HEK *); + aux->xhv_name_count = new_count; (aux->xhv_name_u.xhvnameu_names)[count] = share_hek(name, (flags & SVf_UTF8 ? -(I32)len : (I32)len), hash); } else { -- 2.10.2 ```
p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

Hello\,

I've attached the poc and the asan log. Tested on git version of perl.

Configure options​:

“./Configure -des -Dusedevel -DDEBUGGING -Dcc=clang -Doptimize=-O2 -Accflags="-fsanitize=address -fsanitize-coverage=edge" -Aldflags="-fsanitize=address -fsanitize-coverage=edge" -Alddlflags=-shared"

Information about configuration​:

Distributor ID​: Ubuntu Description​: Ubuntu 16.10 Release​: 16.10 Codename​: yakkety Arch​: x86_64

Best Regards\, Marcin T.

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

new-heap-buffer-overflow-f61-220-655

p5pRT commented 7 years ago

From mtowalski@pentest.net.pl

/usr/bin/llvm-symbolizer perl​: warning​: Setting locale failed. perl​: warning​: Please check that your locale settings​:   LANGUAGE = (unset)\,   LC_ALL = (unset)\,   LC_CTYPE = "UTF-8"\,   LANG = "en_US.UTF-8"   are supported and installed on your system. perl​: warning​: Falling back to a fallback locale ("en_US.UTF-8"). Useless use of a variable in void context at ./new-heap-buffer-overflow-f61-220-655 line 21. Useless use of a variable in void context at ./new-heap-buffer-overflow-f61-220-655 line 21. Scalar found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 25\, near "$pad"   (Missing semicolon on previous line?) Backslash found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 29\, near ""'\\x($enc\, " \"   (Missing operator before \?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 29\, near "$padding'$chr'"   (Missing operator before '$chr'?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 29\, near "sprintf ""   (Missing semicolon on previous line?) Scalar found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 29\, near "'\\x($enc\, " \n$padding'$chr"   (Missing operator before $chr?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "sprintf "'"   (Might be a runaway multi-line '' string starting on line 29)   (Missing semicolon on previous line?) Backslash found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "sprintf "'\"   (Do you need to predeclare sprintf?) Scalar found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "'\\x($enc\, " \n$padding'$chr"   (Missing operator before $chr?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "$chr'"\, $chr\, tf "'"   (Missing operator before '"\, $chr\, tf "'?) Backslash found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "'"\, $chr\, tf "'\"   (Missing operator before \?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "$padding'$chr'"   (Missing operator before '$chr'?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "'$chr'"\, $chrintf ""   (Missing operator before "\, $chrintf "?) Scalar found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "'\\x($enc\, " g'$chr"   (Missing operator before $chr?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "$chr'"\, sprintf " " \n$padding'"   (Missing operator before '"\, sprintf " " \n$padding'?) Scalar found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "'"\, sprintf " " \n$padding'$chr"   (Missing operator before $chr?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "$chr'"\, $chr\, $f "'"   (Missing operator before '"\, $chr\, $f "'?) Backslash found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "'"\, $chr\, $f "'\"   (Missing operator before \?) Bareword found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "' with $pbefore it"before it")' with"   (Missing operator before with?) String found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near ")' with $pbefore it"before it")'"   (Missing operator before ' with $pbefore it"before it")'?) Bareword found where operator expected at ./new-heap-buffer-overflow-f61-220-655 line 30\, near "' with $pbefore it"before it")' with"   (Missing operator before with?)

==11968==ERROR​: AddressSanitizer​: heap-buffer-overflow on address 0x619000000980 at pc 0x0000008fff62 bp 0x7ffe7c6f9440 sp 0x7ffe7c6f9438 WRITE of size 8 at 0x619000000980 thread T0   #0 0x8fff61 in Perl_sv_2mortal /home/mtowalski/Fuzzing/Programs/perl-git/sv.c​:9324​:5   #1 0x6d4220 in S_missingterm /home/mtowalski/Fuzzing/Programs/perl-git/toke.c​:596​:10   #2 0x698655 in Perl_yylex /home/mtowalski/Fuzzing/Programs/perl-git/toke.c​:6869​:6   #3 0x6e834d in Perl_yyparse /home/mtowalski/Fuzzing/Programs/perl-git/perly.c​:340​:34   #4 0x5e3dc6 in S_parse_body /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:2377​:9   #5 0x5db300 in perl_parse /home/mtowalski/Fuzzing/Programs/perl-git/perl.c​:1692​:2   #6 0x5242ce in main /home/mtowalski/Fuzzing/Programs/perl-git/perlmain.c​:121​:18   #7 0x7fde8b6d53f0 in __libc_start_main /build/glibc-jxM2Ev/glibc-2.24/csu/../csu/libc-start.c​:291   #8 0x4356f9 in _start (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4356f9)

0x619000000980 is located 0 bytes to the right of 1024-byte region [0x619000000580\,0x619000000980) allocated by thread T0 here​:   #0 0x4eb0a8 in malloc (/home/mtowalski/Fuzzing/Programs/perl-git/perl+0x4eb0a8)   #1 0x80087e in Perl_safesysmalloc /home/mtowalski/Fuzzing/Programs/perl-git/util.c​:153​:21   #2 0x7fde8b6d53f0 in __libc_start_main /build/glibc-jxM2Ev/glibc-2.24/csu/../csu/libc-start.c​:291

SUMMARY​: AddressSanitizer​: heap-buffer-overflow /home/mtowalski/Fuzzing/Programs/perl-git/sv.c​:9324​:5 in Perl_sv_2mortal Shadow bytes around the buggy address​:   0x0c327fff80e0​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   0x0c327fff80f0​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   0x0c327fff8100​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   0x0c327fff8110​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   0x0c327fff8120​: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c327fff8130​:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c327fff8140​: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c327fff8150​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff8160​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff8170​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd   0x0c327fff8180​: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes)​:   Addressable​: 00   Partially addressable​: 01 02 03 04 05 06 07   Heap left redzone​: fa   Freed heap region​: fd   Stack left redzone​: f1   Stack mid redzone​: f2   Stack right redzone​: f3   Stack after return​: f5   Stack use after scope​: f8   Global redzone​: f9   Global init order​: f6   Poisoned by user​: f7   Container overflow​: fc   Array cookie​: ac   Intra object redzone​: bb   ASan internal​: fe   Left alloca redzone​: ca   Right alloca redzone​: cb ==11968==ABORTING

p5pRT commented 7 years ago

From @iabyn

On Wed\, Mar 01\, 2017 at 06​:07​:23AM -0800\, Hugo van der Sanden via RT wrote​:

On Tue\, 28 Feb 2017 10​:01​:47 -0800\, hv wrote​:

I did start working a bit more on it today\, covering all the Renew() cases annotated in my previous message except for hv.c​:Perl_hv_ename_add()\, which needs a bit more effort.

Attached that additional piece\, as well as a fixup for porting/customized.

Attached is the first pass at those\, I need to go back through to make sure I ha ven't messed up (but it passes a basic 'make test').

My feeling about your patches is that they should all be applied now\, except for the following\, which should be left for 5.27.1 or whatever​:

  0001-OS2-update-size-after-Renew.patch   This is only dependent on the number of threads running\, which   will never even nearly approach wraparound. Also it affects a   platform we (presumably) where we can't compile or test.  
  0005-Scalar-List-Utils-update-size-after-Renew.patch   0001-Scalar-List-Utils-fixup.patch   This code path is only used in 5.6.x and earlier\, and would only   trigger a wrap croak if a sub had recursed so deeply that the   context stack had gradually grown to consume most of memory. But   all the local state for each sub (new lexical vars etc) would have   consumed all memory long before the context stack could wrap. So I   think this is just a case of providing it to the upstream   maintainer for completeness. This avoiding messign with a cpan/   module after code freeze.

  0002-Perl_hv_ename_add-update-size-after-Renew.patch   This is adding to a stash's list of effective names. I can't   think that the list could ever get near wrapping point without   having long since exhausted memory from allocating string buffers   for the actual names themselves. Also\, the function itself is a   bit tricksy\, using a negative count to indicate something or   another\, which makes me slightly less than 100% certain the patch   is correct (it almost certainly is\, but hey\, lets wait for   5.27.1?)

As for the others\, they all look good to me. Some parts of some of them could perhaps be argued as not being theoretically possible to exploit\, but I think they might as well all go in.

Can you provide any tests? Perhaps some fresh_perl_is()es that expect an eval to catch a 'wrap' croak\, followed by some code that allocates a lot of things that will overrun whatever stack has got a screwed up PL_foo_max var? I could have a go at this if you want.

I've made the assumption that retaining existing "catchable die" semantics is ne cessary; it's open for debate whether that's correct.

We generally seem to do a catchable croak() on memory wrap issues\, so my gut feeling is that we should continue to do so.

I think it's also worth discussing whether we should go further. Most of these p athways involve additional calculations that can wrap\, without taking appropriat e steps. I'd have loved to provide some new macros that could have moved more of the logic into a separate place (eg a "Renew and update my size in the right or der" macro)\, but sadly I found so little regularity there seemed little I could do there.

That sounds like something to look at further post 5.26.0. Ideally we could reach a situation where a bare Renew() is no longer directly used in the core\, and is deprecated for XS use.

I'll look more at your analysis; I already answered my first two objections whil e writing this. :)

My analysis may well have been wrong. (Stranger things have been known ;-).)

-- Justice is when you get what you deserve. Law is when you get what you pay for.

p5pRT commented 7 years ago

From @hvds

On Mon\, 06 Mar 2017 09​:01​:27 -0800\, davem wrote​:

My feeling about your patches is that they should all be applied now\, except for the following\, which should be left for 5.27.1 or whatever​:

0001-OS2-update-size-after-Renew.patch [...] 0005-Scalar-List-Utils-update-size-after-Renew.patch 0001-Scalar-List-Utils-fixup.patch [...] 0002-Perl_hv_ename_add-update-size-after-Renew.patch

I'm comfortable with that; I assume it needs some Pumpkin juice to ok at this point though. That'd be these 3​:   0002-WIN32-update-size-after-Renew.patch   0003-reentr-update-size-after-Renew.patch   0004-update-size-after-Renew.patch

Did you also have a chance to think further about the other unchecked additions I noted\, in EXTEND_MORTAL (once) and Perl_tmps_grow_p (twice)? I need to go and look at those again myself as well\, and it's a class of bugs that similarly merits a full audit.

Can you provide any tests? Perhaps some fresh_perl_is()es that expect an eval to catch a 'wrap' croak\, followed by some code that allocates a lot of things that will overrun whatever stack has got a screwed up PL_foo_max var? I could have a go at this if you want.

Thanks\, I'd appreciate it if you could give that a go.

Hugo

p5pRT commented 7 years ago

From @iabyn

On Mon\, Mar 06\, 2017 at 09​:36​:51AM -0800\, Hugo van der Sanden via RT wrote​:

Did you also have a chance to think further about the other unchecked additions I noted\, in EXTEND_MORTAL (once) and Perl_tmps_grow_p (twice)? I need to go and look at those again myself as well\, and it's a class of bugs that similarly merits a full audit.

Do you mean where EXTEND_MORTAL does

  eMiX = PL_tmps_ix + (n)

and Perl_tmps_grow_p does

  extend_to += something;   ...   Renew(....\, extend_to + 1)

where both are in danger of wraparound?

I think they would be hard to fix for 5.26.0. Have a quick look at the various _MEM_WRAP_* macros in handy.h​: these were mostly my work\, and took *many* iterations to

  a) be secure;   b) be efficient (especially making checks at compile-time where   possible);   c) not to endlessly emit compiler warnings like   "comparison is always false due to limited range of data type"   for every permutation of C and C++ compiler and 32\, 64 and 32/64   bit platforms.

So I think that should be left for 5.27.x. I suspect that it may require changing the interface of the (non-API) function Perl_tmps_grow_p()\, e.g. to pass n\, rather than (PL_tmps_ix+n) to it. Macros/funcs for growing other stacks probably also need some TLC. I've had on my todo list quite a while now an intention to generally overhaul perl's various allocation mechanisms\, especially over-allocation (where each layer of code adds its own "and a bit more for good measure" additional growth factor. This is especially bad for PVX buffers.

Can you provide any tests? Perhaps some fresh_perl_is()es that expect an eval to catch a 'wrap' croak\, followed by some code that allocates a lot of things that will overrun whatever stack has got a screwed up PL_foo_max var? I could have a go at this if you want.

Thanks\, I'd appreciate it if you could give that a go.

I'll do that now.

-- No matter how many dust sheets you use\, you will get paint on the carpet.

p5pRT commented 7 years ago

From @hvds

On Tue\, 07 Mar 2017 04​:10​:21 -0800\, davem wrote​:

Do you mean where EXTEND_MORTAL does

eMiX = PL\_tmps\_ix \+ \(n\)

and Perl_tmps_grow_p does

extend\_to \+= something;
\.\.\.
Renew\(\.\.\.\.\, extend\_to \+ 1\)

where both are in danger of wraparound?

Yes.

I think they would be hard to fix for 5.26.0.

Ok\, that was pretty much the conclusion I was heading towards.

I'll [try to add some tests] now.

Thanks!

Hugo

p5pRT commented 7 years ago

From @hvds

This is the same issue as [perl #130841]\, presumably triggered by the (7 .. 2240639990569944149) range​: applying the Perl_tmps_grow_p() fragment from that ticket is enough to avoid triggering the bad write.

I'll merge them.

Hugo

p5pRT commented 7 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 7 years ago

From @iabyn

On Tue\, Mar 07\, 2017 at 05​:18​:23AM -0800\, Hugo van der Sanden via RT wrote​:

I'll [try to add some tests] now.

I've written a test\, but it turns out that the only one which can be safely done in the test suite is the original 1..(~0 >> 1) which was the subject of this ticket​: all the other ones require improbable conditions such as a win32 folder with billions of files in it\, which are not amenable to testing.

But when I applied your 000[234] patches to my system\, reentr.c failed to compile. I spotted one simple typo\, &PL_reentrant_buffer-_hostent_size missing the '>'\, and the RenewDouble macro was missing a 'STMT_END'\, but after fixing those\, it still failed to compile\, and I was left in macro expansion hell\, so I gave up. This was on a threaded build. Do you fancy fixing this?

-- Counsellor Troi states something other than the blindingly obvious.   -- Things That Never Happen in "Star Trek" #16

p5pRT commented 7 years ago

From @hvds

On Tue\, 07 Mar 2017 08​:04​:14 -0800\, davem wrote​:

But when I applied your 000[234] patches to my system\, reentr.c failed to compile.

Ugh\, it never occurred to me a non-threaded build wouldn't exercise that one.

It looks like the parens around (type) in RenewDouble were the problem. New version of that commit attached\, with all three fixes. This now at least passes minitest on a threaded build.

Hugo

p5pRT commented 7 years ago

From @hvds

0003b-reentr-update-size-after-Renew.patch ```diff From 5d94bf78d5b8072db5927090607839694f1c0cbf Mon Sep 17 00:00:00 2001 From: Hugo van der Sanden Date: Tue, 28 Feb 2017 11:21:55 +0000 Subject: [PATCH] reentr: update size after Renew Setting it before Renew can cause problems if the Renew fails. Required 'make regen'. --- reentr.c | 37 +++++++++++++++++++------------------ regen/reentr.pl | 37 +++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/reentr.c b/reentr.c index c464acc..70b971b 100644 --- a/reentr.c +++ b/reentr.c @@ -33,6 +33,13 @@ #include "perl.h" #include "reentr.h" +#define RenewDouble(data_pointer, size_pointer, type) \ + STMT_START { \ + const size_t size = *(size_pointer) * 2; \ + Renew((data_pointer), (size), type); \ + *(size_pointer) = size; \ + } STMT_END + void Perl_reentrant_size(pTHX) { PERL_UNUSED_CONTEXT; @@ -326,9 +333,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_hostent_size *= 2; - Renew(PL_reentrant_buffer->_hostent_buffer, - PL_reentrant_buffer->_hostent_size, char); + RenewDouble(PL_reentrant_buffer->_hostent_buffer, + &PL_reentrant_buffer->_hostent_size, char); switch (PL_op->op_type) { case OP_GHBYADDR: p0 = va_arg(ap, void *); @@ -359,9 +365,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Gid_t gid; - PL_reentrant_buffer->_grent_size *= 2; - Renew(PL_reentrant_buffer->_grent_buffer, - PL_reentrant_buffer->_grent_size, char); + RenewDouble(PL_reentrant_buffer->_grent_buffer, + &PL_reentrant_buffer->_grent_size, char); switch (PL_op->op_type) { case OP_GGRNAM: p0 = va_arg(ap, void *); @@ -394,9 +399,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Netdb_net_t net; - PL_reentrant_buffer->_netent_size *= 2; - Renew(PL_reentrant_buffer->_netent_buffer, - PL_reentrant_buffer->_netent_size, char); + RenewDouble(PL_reentrant_buffer->_netent_buffer, + &PL_reentrant_buffer->_netent_size, char); switch (PL_op->op_type) { case OP_GNBYADDR: net = va_arg(ap, Netdb_net_t); @@ -426,9 +430,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Uid_t uid; - PL_reentrant_buffer->_pwent_size *= 2; - Renew(PL_reentrant_buffer->_pwent_buffer, - PL_reentrant_buffer->_pwent_size, char); + RenewDouble(PL_reentrant_buffer->_pwent_buffer, + &PL_reentrant_buffer->_pwent_size, char); switch (PL_op->op_type) { case OP_GPWNAM: p0 = va_arg(ap, void *); @@ -462,9 +465,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_protoent_size *= 2; - Renew(PL_reentrant_buffer->_protoent_buffer, - PL_reentrant_buffer->_protoent_size, char); + RenewDouble(PL_reentrant_buffer->_protoent_buffer, + &PL_reentrant_buffer->_protoent_size, char); switch (PL_op->op_type) { case OP_GPBYNAME: p0 = va_arg(ap, void *); @@ -492,9 +494,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_servent_size *= 2; - Renew(PL_reentrant_buffer->_servent_buffer, - PL_reentrant_buffer->_servent_size, char); + RenewDouble(PL_reentrant_buffer->_servent_buffer, + &PL_reentrant_buffer->_servent_size, char); switch (PL_op->op_type) { case OP_GSBYNAME: p0 = va_arg(ap, void *); diff --git a/regen/reentr.pl b/regen/reentr.pl index 802b8db..f8f78a5 100644 --- a/regen/reentr.pl +++ b/regen/reentr.pl @@ -773,6 +773,13 @@ print $c <<"EOF"; #include "perl.h" #include "reentr.h" +#define RenewDouble(data_pointer, size_pointer, type) \\ + STMT_START { \\ + const size_t size = *(size_pointer) * 2; \\ + Renew((data_pointer), (size), type); \\ + *(size_pointer) = size; \\ + } STMT_END + void Perl_reentrant_size(pTHX) { PERL_UNUSED_CONTEXT; @@ -840,9 +847,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_hostent_size *= 2; - Renew(PL_reentrant_buffer->_hostent_buffer, - PL_reentrant_buffer->_hostent_size, char); + RenewDouble(PL_reentrant_buffer->_hostent_buffer, + &PL_reentrant_buffer->_hostent_size, char); switch (PL_op->op_type) { case OP_GHBYADDR: p0 = va_arg(ap, void *); @@ -873,9 +879,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Gid_t gid; - PL_reentrant_buffer->_grent_size *= 2; - Renew(PL_reentrant_buffer->_grent_buffer, - PL_reentrant_buffer->_grent_size, char); + RenewDouble(PL_reentrant_buffer->_grent_buffer, + &PL_reentrant_buffer->_grent_size, char); switch (PL_op->op_type) { case OP_GGRNAM: p0 = va_arg(ap, void *); @@ -908,9 +913,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Netdb_net_t net; - PL_reentrant_buffer->_netent_size *= 2; - Renew(PL_reentrant_buffer->_netent_buffer, - PL_reentrant_buffer->_netent_size, char); + RenewDouble(PL_reentrant_buffer->_netent_buffer, + &PL_reentrant_buffer->_netent_size, char); switch (PL_op->op_type) { case OP_GNBYADDR: net = va_arg(ap, Netdb_net_t); @@ -940,9 +944,8 @@ Perl_reentrant_retry(const char *f, ...) #endif { Uid_t uid; - PL_reentrant_buffer->_pwent_size *= 2; - Renew(PL_reentrant_buffer->_pwent_buffer, - PL_reentrant_buffer->_pwent_size, char); + RenewDouble(PL_reentrant_buffer->_pwent_buffer, + &PL_reentrant_buffer->_pwent_size, char); switch (PL_op->op_type) { case OP_GPWNAM: p0 = va_arg(ap, void *); @@ -976,9 +979,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_protoent_size *= 2; - Renew(PL_reentrant_buffer->_protoent_buffer, - PL_reentrant_buffer->_protoent_size, char); + RenewDouble(PL_reentrant_buffer->_protoent_buffer, + &PL_reentrant_buffer->_protoent_size, char); switch (PL_op->op_type) { case OP_GPBYNAME: p0 = va_arg(ap, void *); @@ -1006,9 +1008,8 @@ Perl_reentrant_retry(const char *f, ...) PERL_REENTRANT_MAXSIZE / 2) #endif { - PL_reentrant_buffer->_servent_size *= 2; - Renew(PL_reentrant_buffer->_servent_buffer, - PL_reentrant_buffer->_servent_size, char); + RenewDouble(PL_reentrant_buffer->_servent_buffer, + &PL_reentrant_buffer->_servent_size, char); switch (PL_op->op_type) { case OP_GSBYNAME: p0 = va_arg(ap, void *); -- 2.10.2 ```
p5pRT commented 7 years ago

From @iabyn

On Tue\, Mar 07\, 2017 at 10​:06​:49AM -0800\, Hugo van der Sanden via RT wrote​:

Ugh\, it never occurred to me a non-threaded build wouldn't exercise that one.

That's the perl core for you ;-)

This now at least passes minitest on a threaded build.

Thanks. Builds on my system now.

Attached is a test for this issue. I'd like to check it on my 32-bit system when I get home this evening\, before declaring it ok to apply. Then I suggest you apply your fixes to blead\, and you can apply my test too if you want.

-- Please note that ash-trays are provided for the use of smokers\, whereas the floor is provided for the use of all patrons.   -- Bill Royston

p5pRT commented 7 years ago

From @iabyn

0001-add-range.t-test-for-RT-130841.patch ```diff From 14673c3fe0159354ab74d972be4537d8e5004409 Mon Sep 17 00:00:00 2001 From: David Mitchell Date: Tue, 7 Mar 2017 15:22:49 +0000 Subject: [PATCH] add range.t test for RT #130841 --- t/op/range.t | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/t/op/range.t b/t/op/range.t index e58a39c..02a38e0 100644 --- a/t/op/range.t +++ b/t/op/range.t @@ -9,7 +9,7 @@ BEGIN { use Config; -plan (145); +plan (146); is(join(':',1..5), '1:2:3:4:5'); @@ -417,4 +417,33 @@ is( ( join ' ', map { join '', map ++$_, 'a'..'d' } 1..2 ), 'bcde bcde', $s = ''; for (1..2) { for ('a'..'d') { $s .= ++$_ } $s.=' ' if $_==1; } is( $s, 'bcde bcde','modifiable alpha counting loop counter' ); -# EOF +# RT #130841 +# generating an extreme range triggered a croak, which if caught, +# left the temps stack small but with a very large PL_tmps_max + +fresh_perl_like(<<'EOF', qr/\Aok 1 ok 2\Z/, {}, "RT #130841"); +my $max_iv = (~0 >> 1); +eval { + my @range = 1..($max_iv - 1); +}; +if ($@ =~ /panic: memory wrap|Out of memory/) { + print "ok 1"; +} +else { + print "unexpected err status: [$@]"; +} + +# create and push lots of temps +my $max = 10_000; +my @ints = map $_+1, 0..($max-1); +my $sum = 0; +$sum += $_ for @ints; +my $exp = $max*($max+1)/2; +if ($sum == $exp) { + print " ok 2"; +} +else { + print " unexpected sum: [$sum]; expected: [$exp]"; +} +EOF + -- 2.4.11 ```
p5pRT commented 7 years ago

From @hvds

On Wed\, 08 Mar 2017 00​:41​:11 -0800\, davem wrote​:

That's the perl core for you ;-)

There's a win32/wince part as well\, is someone in a position to do at least a build test with those ("0002-WIN32-update-size-after-Renew.patch")? Alternatively if the timeline for release permits I could first push a smoke-me branch\, with the clean version of the 3 patches plus your test.

Attached is a test for this issue. I'd like to check it on my 32-bit system when I get home this evening\, before declaring it ok to apply. Then I suggest you apply your fixes to blead\, and you can apply my test too if you want.

Sawyer\, are you happy to ok this\, with or without a preceding smoke-me? We're talking about​:

0001-add-range.t-test-for-RT-130841.patch 0002-WIN32-update-size-after-Renew.patch 0003b-reentr-update-size-after-Renew.patch 0004-update-size-after-Renew.patch

Hugo

p5pRT commented 7 years ago

From @iabyn

On Wed\, Mar 08\, 2017 at 08​:40​:18AM +0000\, Dave Mitchell wrote​:

Attached is a test for this issue. I'd like to check it on my 32-bit system when I get home this evening

Now passed on a 32-bit and 32-bit with -Duse64bitint system.

-- Justice is when you get what you deserve. Law is when you get what you pay for.

p5pRT commented 7 years ago

From @iabyn

On Thu\, Mar 09\, 2017 at 10​:16​:34PM +0000\, Dave Mitchell wrote​:

On Wed\, Mar 08\, 2017 at 08​:40​:18AM +0000\, Dave Mitchell wrote​:

Attached is a test for this issue. I'd like to check it on my 32-bit system when I get home this evening

Now passed on a 32-bit and 32-bit with -Duse64bitint system.

I have now merged into blead the agreed subsut of Hugo's patch set\, plus my test.

-- "You may not work around any technical limitations in the software"   -- Windows Vista license

p5pRT commented 7 years ago

From @tonycoz

On Wed\, 15 Mar 2017 02​:28​:46 -0700\, davem wrote​:

On Thu\, Mar 09\, 2017 at 10​:16​:34PM +0000\, Dave Mitchell wrote​:

On Wed\, Mar 08\, 2017 at 08​:40​:18AM +0000\, Dave Mitchell wrote​:

Attached is a test for this issue. I'd like to check it on my 32-bit system when I get home this evening

Now passed on a 32-bit and 32-bit with -Duse64bitint system.

I have now merged into blead the agreed subsut of Hugo's patch set\, plus my test.

Do we consider any part of this as a security issue?

I'd tend to think the buffer write overflow was a security issue\, while large range limits below the overflow boundary would cause a DoS (either allocation failing\, or an eventual process kill on say Linux with overcommit enabled) as opposed to writing beyond the end of the allocated temps stack.

As Dave pointed out a mitigating factor is that the values written are addresses of SVs rather than arbritrary attacker supplied data.

Tony

p5pRT commented 6 years ago

From @khwilliamson

On Wed\, 05 Jul 2017 19​:07​:09 -0700\, tonyc wrote​:

On Wed\, 15 Mar 2017 02​:28​:46 -0700\, davem wrote​:

On Thu\, Mar 09\, 2017 at 10​:16​:34PM +0000\, Dave Mitchell wrote​:

On Wed\, Mar 08\, 2017 at 08​:40​:18AM +0000\, Dave Mitchell wrote​:

Attached is a test for this issue. I'd like to check it on my 32- bit system when I get home this evening

Now passed on a 32-bit and 32-bit with -Duse64bitint system.

I have now merged into blead the agreed subsut of Hugo's patch set\, plus my test.

Do we consider any part of this as a security issue?

I'd tend to think the buffer write overflow was a security issue\, while large range limits below the overflow boundary would cause a DoS (either allocation failing\, or an eventual process kill on say Linux with overcommit enabled) as opposed to writing beyond the end of the allocated temps stack.

As Dave pointed out a mitigating factor is that the values written are addresses of SVs rather than arbritrary attacker supplied data.

Tony

So this is in blead\, and apparently not backported to other releases. What should be done?

-- Karl Williamson

p5pRT commented 6 years ago

From @xsawyerx

On 6 February 2018 at 22​:26\, Karl Williamson via RT \perl5\-security\-report\-followup@&#8203;perl\.org wrote​:

On Wed\, 05 Jul 2017 19​:07​:09 -0700\, tonyc wrote​:

On Wed\, 15 Mar 2017 02​:28​:46 -0700\, davem wrote​:

On Thu\, Mar 09\, 2017 at 10​:16​:34PM +0000\, Dave Mitchell wrote​:

On Wed\, Mar 08\, 2017 at 08​:40​:18AM +0000\, Dave Mitchell wrote​:

Attached is a test for this issue. I'd like to check it on my 32- bit system when I get home this evening

Now passed on a 32-bit and 32-bit with -Duse64bitint system.

I have now merged into blead the agreed subsut of Hugo's patch set\, plus my test.

Do we consider any part of this as a security issue?

I'd tend to think the buffer write overflow was a security issue\, while large range limits below the overflow boundary would cause a DoS (either allocation failing\, or an eventual process kill on say Linux with overcommit enabled) as opposed to writing beyond the end of the allocated temps stack.

As Dave pointed out a mitigating factor is that the values written are addresses of SVs rather than arbritrary attacker supplied data.

Tony

So this is in blead\, and apparently not backported to other releases. What should be done?

I would much prefer we backport this.

p5pRT commented 6 years ago

From @iabyn

On Wed\, Feb 07\, 2018 at 11​:42​:43AM +0200\, Sawyer X wrote​:

On 6 February 2018 at 22​:26\, Karl Williamson via RT \perl5\-security\-report\-followup@&#8203;perl\.org wrote​:

On Wed\, 05 Jul 2017 19​:07​:09 -0700\, tonyc wrote​:

On Wed\, 15 Mar 2017 02​:28​:46 -0700\, davem wrote​:

On Thu\, Mar 09\, 2017 at 10​:16​:34PM +0000\, Dave Mitchell wrote​:

On Wed\, Mar 08\, 2017 at 08​:40​:18AM +0000\, Dave Mitchell wrote​:

Attached is a test for this issue. I'd like to check it on my 32- bit system when I get home this evening

Now passed on a 32-bit and 32-bit with -Duse64bitint system.

I have now merged into blead the agreed subsut of Hugo's patch set\, plus my test.

Do we consider any part of this as a security issue?

I'd tend to think the buffer write overflow was a security issue\, while large range limits below the overflow boundary would cause a DoS (either allocation failing\, or an eventual process kill on say Linux with overcommit enabled) as opposed to writing beyond the end of the allocated temps stack.

As Dave pointed out a mitigating factor is that the values written are addresses of SVs rather than arbritrary attacker supplied data.

Tony

So this is in blead\, and apparently not backported to other releases. What should be done?

I would much prefer we backport this.

Note that these fixes were applied as v5.25.10-74-g95d8e32b92\, so are already present in 5.26.x. The only issue whether to backport them to maint-5.24. We currently have perl-5.24.4-RC1 released\, with perl-5.24.4 ready to go now\, soon after which 5.24 slips out of maintenance.

Personally my gut felling is to leave maint.5.24 alone.

-- "There's something wrong with our bloody ships today\, Chatfield."   -- Admiral Beatty at the Battle of Jutland\, 31st May 1916.

p5pRT commented 6 years ago

From @xsawyerx

On 9 April 2018 at 19​:40\, Dave Mitchell \davem@&#8203;iabyn\.com wrote​:

On Wed\, Feb 07\, 2018 at 11​:42​:43AM +0200\, Sawyer X wrote​:

On 6 February 2018 at 22​:26\, Karl Williamson via RT \perl5\-security\-report\-followup@&#8203;perl\.org wrote​:

On Wed\, 05 Jul 2017 19​:07​:09 -0700\, tonyc wrote​:

On Wed\, 15 Mar 2017 02​:28​:46 -0700\, davem wrote​:

On Thu\, Mar 09\, 2017 at 10​:16​:34PM +0000\, Dave Mitchell wrote​:

On Wed\, Mar 08\, 2017 at 08​:40​:18AM +0000\, Dave Mitchell wrote​:

Attached is a test for this issue. I'd like to check it on my 32- bit system when I get home this evening

Now passed on a 32-bit and 32-bit with -Duse64bitint system.

I have now merged into blead the agreed subsut of Hugo's patch set\, plus my test.

Do we consider any part of this as a security issue?

I'd tend to think the buffer write overflow was a security issue\, while large range limits below the overflow boundary would cause a DoS (either allocation failing\, or an eventual process kill on say Linux with overcommit enabled) as opposed to writing beyond the end of the allocated temps stack.

As Dave pointed out a mitigating factor is that the values written are addresses of SVs rather than arbritrary attacker supplied data.

Tony

So this is in blead\, and apparently not backported to other releases. What should be done?

I would much prefer we backport this.

Note that these fixes were applied as v5.25.10-74-g95d8e32b92\, so are already present in 5.26.x. The only issue whether to backport them to maint-5.24. We currently have perl-5.24.4-RC1 released\, with perl-5.24.4 ready to go now\, soon after which 5.24 slips out of maintenance.

Personally my gut felling is to leave maint.5.24 alone.

That makes sense.

p5pRT commented 6 years ago

From @khwilliamson

So\, this is in the field in 5.26.3. Is there a reason not to close this ticket? -- Karl Williamson