@@ -688,7 +688,34 @@ SRE_INFO(SRE_STATE* state, SRE_CODE* pattern)
688688}
689689#endif
690690
691- /* macros to preserve lastmark in case of backtracking */
691+ /* The macros below should be used to protect recursive SRE_MATCH()
692+ * calls that *failed* and do *not* return immediately (IOW, those
693+ * that will backtrack). Explaining:
694+ *
695+ * - Recursive SRE_MATCH() returned true: that's usually a success
696+ * (besides atypical cases like ASSERT_NOT), therefore there's no
697+ * reason to restore lastmark;
698+ *
699+ * - Recursive SRE_MATCH() returned false but the current SRE_MATCH()
700+ * is returning to the caller: If the current SRE_MATCH() is the
701+ * top function of the recursion, returning false will be a matching
702+ * failure, and it doesn't matter where lastmark is pointing to.
703+ * If it's *not* the top function, it will be a recursive SRE_MATCH()
704+ * failure by itself, and the calling SRE_MATCH() will have to deal
705+ * with the failure by the same rules explained here (it will restore
706+ * lastmark by itself if necessary);
707+ *
708+ * - Recursive SRE_MATCH() returned false, and will continue the
709+ * outside 'for' loop: must be protected when breaking, since the next
710+ * OP could potentially depend on lastmark;
711+ *
712+ * - Recursive SRE_MATCH() returned false, and will be called again
713+ * inside a local for/while loop: must be protected between each
714+ * loop iteration, since the recursive SRE_MATCH() could do anything,
715+ * and could potentially depend on lastmark.
716+ *
717+ * For more information, check the discussion at SF patch #712900.
718+ */
692719#define LASTMARK_SAVE () \
693720 do { \
694721 lastmark = state->lastmark; \
@@ -942,18 +969,18 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
942969 /* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
943970 TRACE (("|%p|%p|BRANCH\n" , pattern , ptr ));
944971 LASTMARK_SAVE ();
972+ if (state -> repeat ) {
973+ i = mark_save (state , 0 , lastmark , & mark_stack_base );
974+ if (i < 0 )
975+ return i ;
976+ }
945977 for (; pattern [0 ]; pattern += pattern [0 ]) {
946978 if (pattern [1 ] == SRE_OP_LITERAL &&
947979 (ptr >= end || (SRE_CODE ) * ptr != pattern [2 ]))
948980 continue ;
949981 if (pattern [1 ] == SRE_OP_IN &&
950982 (ptr >= end || !SRE_CHARSET (pattern + 3 , (SRE_CODE ) * ptr )))
951983 continue ;
952- if (state -> repeat ) {
953- i = mark_save (state , 0 , lastmark , & mark_stack_base );
954- if (i < 0 )
955- return i ;
956- }
957984 state -> ptr = ptr ;
958985 i = SRE_MATCH (state , pattern + 1 , level + 1 );
959986 if (i )
@@ -1092,12 +1119,12 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
10921119 c = SRE_COUNT (state , pattern + 3 , 1 , level + 1 );
10931120 if (c < 0 )
10941121 return c ;
1095- LASTMARK_RESTORE ();
10961122 if (c == 0 )
10971123 break ;
10981124 assert (c == 1 );
10991125 ptr ++ ;
11001126 count ++ ;
1127+ LASTMARK_RESTORE ();
11011128 }
11021129 }
11031130 return 0 ;
@@ -1140,8 +1167,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
11401167
11411168 TRACE (("|%p|%p|MAX_UNTIL %d\n" , pattern , ptr , count ));
11421169
1143- LASTMARK_SAVE ();
1144-
11451170 if (count < rp -> pattern [1 ]) {
11461171 /* not enough matches */
11471172 rp -> count = count ;
@@ -1151,14 +1176,14 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
11511176 return i ;
11521177 rp -> count = count - 1 ;
11531178 state -> ptr = ptr ;
1154- LASTMARK_RESTORE ();
11551179 return 0 ;
11561180 }
11571181
11581182 if (count < rp -> pattern [2 ] || rp -> pattern [2 ] == 65535 ) {
11591183 /* we may have enough matches, but if we can
11601184 match another item, do so */
11611185 rp -> count = count ;
1186+ LASTMARK_SAVE ();
11621187 i = mark_save (state , 0 , lastmark , & mark_stack_base );
11631188 if (i < 0 )
11641189 return i ;
@@ -1167,9 +1192,9 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
11671192 if (i )
11681193 return i ;
11691194 i = mark_restore (state , 0 , lastmark , & mark_stack_base );
1170- LASTMARK_RESTORE ();
11711195 if (i < 0 )
11721196 return i ;
1197+ LASTMARK_RESTORE ();
11731198 rp -> count = count - 1 ;
11741199 state -> ptr = ptr ;
11751200 }
@@ -1182,7 +1207,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
11821207 return i ;
11831208 state -> repeat = rp ;
11841209 state -> ptr = ptr ;
1185- LASTMARK_RESTORE ();
11861210 return 0 ;
11871211
11881212 case SRE_OP_MIN_UNTIL :
@@ -1200,8 +1224,6 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
12001224 TRACE (("|%p|%p|MIN_UNTIL %d %p\n" , pattern , ptr , count ,
12011225 rp -> pattern ));
12021226
1203- LASTMARK_SAVE ();
1204-
12051227 if (count < rp -> pattern [1 ]) {
12061228 /* not enough matches */
12071229 rp -> count = count ;
@@ -1211,10 +1233,11 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
12111233 return i ;
12121234 rp -> count = count - 1 ;
12131235 state -> ptr = ptr ;
1214- LASTMARK_RESTORE ();
12151236 return 0 ;
12161237 }
12171238
1239+ LASTMARK_SAVE ();
1240+
12181241 /* see if the tail matches */
12191242 state -> repeat = rp -> prev ;
12201243 i = SRE_MATCH (state , pattern , level + 1 );
@@ -1224,18 +1247,19 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern, int level)
12241247 state -> ptr = ptr ;
12251248 state -> repeat = rp ;
12261249
1227- LASTMARK_RESTORE ();
12281250 if (count >= rp -> pattern [2 ] && rp -> pattern [2 ] != 65535 )
12291251 return 0 ;
12301252
1253+ LASTMARK_RESTORE ();
1254+
12311255 rp -> count = count ;
12321256 /* RECURSIVE */
12331257 i = SRE_MATCH (state , rp -> pattern + 3 , level + 1 );
12341258 if (i )
12351259 return i ;
12361260 rp -> count = count - 1 ;
12371261 state -> ptr = ptr ;
1238- LASTMARK_RESTORE ();
1262+
12391263 return 0 ;
12401264
12411265 default :
0 commit comments