@@ -32,16 +32,39 @@ describe('helpers', () => {
3232
3333 describe ( 'trimEnd' , ( ) => {
3434 it ( 'should remove invisible characters from the end of a string' , ( ) => {
35- const input = 'Hello\u034f\u034f' ;
36- const result = trimEnd ( input ) ;
37- expect ( result ) . toBe ( 'Hello' ) ;
35+ expect ( trimEnd ( 'A ' ) ) . toBe ( 'A' ) ;
36+ expect ( trimEnd ( 'B\n' ) ) . toBe ( 'B' ) ;
37+ expect ( trimEnd ( 'C\t' ) ) . toBe ( 'C' ) ;
38+ expect ( trimEnd ( 'D\r' ) ) . toBe ( 'D' ) ;
39+ expect ( trimEnd ( 'E\u034f' ) ) . toBe ( 'E' ) ;
40+ expect ( trimEnd ( 'F\u17b4' ) ) . toBe ( 'F' ) ;
41+ expect ( trimEnd ( 'G\u17b5' ) ) . toBe ( 'G' ) ;
42+ expect ( trimEnd ( 'F\u2800' ) ) . toBe ( 'F' ) ;
43+ expect ( trimEnd ( 'H\u115f' ) ) . toBe ( 'H' ) ;
44+ expect ( trimEnd ( 'I\u1160' ) ) . toBe ( 'I' ) ;
45+ expect ( trimEnd ( 'J\u3164' ) ) . toBe ( 'J' ) ;
46+ expect ( trimEnd ( 'K\uffa0' ) ) . toBe ( 'K' ) ;
3847 } ) ;
3948
4049 it ( 'should return the same string if no invisible characters are at the end' , ( ) => {
4150 const input = 'Hello' ;
4251 const result = trimEnd ( input ) ;
4352 expect ( result ) . toBe ( 'Hello' ) ;
4453 } ) ;
54+
55+ it ( 'should not hang (ReDoS) on long string of invisible chars' , ( ) => {
56+ const long1 = 'Hello' + '\u3164' . repeat ( 1_000_000 ) ;
57+ const long2 = 'A' . repeat ( 1_000_000 ) + '\u17b5' . repeat ( 1_000_000 ) ;
58+ const long3 = 'B' + '\u034f' . repeat ( 1_000_000 ) + 'C' ;
59+ const long4 = '\u2800' . repeat ( 1_000_000 ) + 'D' ;
60+ const long5 = 'E' . repeat ( 1_000_000 ) + '\u034f' + 'F' ;
61+
62+ expect . soft ( trimEnd ( long1 ) ) . toBe ( 'Hello' ) ;
63+ expect . soft ( trimEnd ( long2 ) ) . toBe ( 'A' . repeat ( 1_000_000 ) ) ;
64+ expect . soft ( trimEnd ( long3 ) ) . toBe ( long3 ) ;
65+ expect . soft ( trimEnd ( long4 ) ) . toBe ( long4 ) ;
66+ expect . soft ( trimEnd ( long5 ) ) . toBe ( long5 ) ;
67+ } , 1_000 ) ;
4568 } ) ;
4669
4770 describe ( 'truncate' , ( ) => {
0 commit comments