@@ -80,6 +80,45 @@ def main():
8080# Tools
8181#
8282
83+ def validate_block_integrity (patch_content ):
84+ """
85+ Validate the integrity of patch blocks before parsing.
86+ Checks for balanced markers and correct sequence.
87+ """
88+ # Check marker balance
89+ search_count = patch_content .count ("<<<<<<< SEARCH" )
90+ separator_count = patch_content .count ("=======" )
91+ replace_count = patch_content .count (">>>>>>> REPLACE" )
92+
93+ if not (search_count == separator_count == replace_count ):
94+ raise ValueError (
95+ f"Malformed patch format: Unbalanced markers - "
96+ f"{ search_count } SEARCH, { separator_count } separator, { replace_count } REPLACE markers"
97+ )
98+
99+ # Check marker sequence
100+ markers = []
101+ for line in patch_content .splitlines ():
102+ line = line .strip ()
103+ if line in ["<<<<<<< SEARCH" , "=======" , ">>>>>>> REPLACE" ]:
104+ markers .append (line )
105+
106+ # Verify correct marker sequence (always SEARCH, SEPARATOR, REPLACE pattern)
107+ for i in range (0 , len (markers ), 3 ):
108+ if i + 2 < len (markers ):
109+ if markers [i ] != "<<<<<<< SEARCH" or markers [i + 1 ] != "=======" or markers [i + 2 ] != ">>>>>>> REPLACE" :
110+ raise ValueError (
111+ f"Malformed patch format: Incorrect marker sequence at position { i } : "
112+ f"Expected [SEARCH, SEPARATOR, REPLACE], got { markers [i :i + 3 ]} "
113+ )
114+
115+ # Check for nested markers in each block
116+ sections = patch_content .split ("<<<<<<< SEARCH" )
117+ for i , section in enumerate (sections [1 :], 1 ): # Skip first empty section
118+ if "<<<<<<< SEARCH" in section and section .find (">>>>>>> REPLACE" ) > section .find ("<<<<<<< SEARCH" ):
119+ raise ValueError (f"Malformed patch format: Nested SEARCH marker in block { i } " )
120+
121+
83122def parse_search_replace_blocks (patch_content ):
84123 """
85124 Parse multiple search-replace blocks from the patch content.
@@ -89,6 +128,9 @@ def parse_search_replace_blocks(patch_content):
89128 search_marker = "<<<<<<< SEARCH"
90129 separator = "======="
91130 replace_marker = ">>>>>>> REPLACE"
131+
132+ # First validate patch integrity
133+ validate_block_integrity (patch_content )
92134
93135 # Use regex to extract all blocks
94136 pattern = f"{ search_marker } \\ n(.*?)\\ n{ separator } \\ n(.*?)\\ n{ replace_marker } "
@@ -125,6 +167,13 @@ def parse_search_replace_blocks(patch_content):
125167
126168 search_text = "\n " .join (lines [search_start :separator_idx ])
127169 replace_text = "\n " .join (lines [separator_idx + 1 :replace_end ])
170+
171+ # Check for markers in the search or replace text
172+ if any (marker in search_text for marker in [search_marker , separator , replace_marker ]):
173+ raise ValueError (f"Block { len (blocks )+ 1 } : Search text contains patch markers" )
174+ if any (marker in replace_text for marker in [search_marker , separator , replace_marker ]):
175+ raise ValueError (f"Block { len (blocks )+ 1 } : Replace text contains patch markers" )
176+
128177 blocks .append ((search_text , replace_text ))
129178
130179 i = replace_end + 1
@@ -136,6 +185,13 @@ def parse_search_replace_blocks(patch_content):
136185 else :
137186 raise ValueError ("Invalid patch format. Expected block format with SEARCH/REPLACE markers." )
138187
188+ # Check for markers in matched content
189+ for i , (search_text , replace_text ) in enumerate (matches ):
190+ if any (marker in search_text for marker in [search_marker , separator , replace_marker ]):
191+ raise ValueError (f"Block { i + 1 } : Search text contains patch markers" )
192+ if any (marker in replace_text for marker in [search_marker , separator , replace_marker ]):
193+ raise ValueError (f"Block { i + 1 } : Replace text contains patch markers" )
194+
139195 return matches
140196
141197
0 commit comments