@@ -177,11 +177,14 @@ def _install_oracle(self, secret="hello"):
177177
178178 def oracle (payload = None , content = False , raise404 = True , ** kwargs ):
179179 # chunk-length probe: recognize every repeat-family builder the search may emit
180- # (REPEAT=MySQL, REPLICATE=MSSQL/Sybase, RPAD=Oracle/Firebird) so a leaked non-MySQL
181- # back-end still exercises the search instead of mis-detecting length 0
182- m = re .search (r"(?:REPEAT|REPLICATE|RPAD)\((?:0x([0-9a-fA-F]{2})|'(.)'),(\d+)" , payload )
180+ # (REPEAT=MySQL, REPLICATE=MSSQL/Sybase, RPAD=Oracle/Firebird) and derive the repeated
181+ # char from the COUNT (the search uses testChar = str(current % 10)), NOT by parsing the
182+ # char literal - so any per-DBMS char encoding ('4' / 0x34 / CHAR(52) / a quote marker)
183+ # still round-trips and the search converges instead of mis-detecting length 0
184+ m = re .search (r"(?:REPEAT|REPLICATE|RPAD)\(.+?,\s*(\d+)" , payload )
183185 if m :
184- raw = (chr (int (m .group (1 ), 16 )) if m .group (1 ) else m .group (2 )) * int (m .group (3 ))
186+ count = int (m .group (1 ))
187+ raw = str (count % 10 ) * count
185188 else :
186189 raw = secret
187190 value = "" .join ("%02X" % _ for _ in bytearray (raw .encode ("latin-1" ))) if re .search (r"\bHEX\(" , payload ) else raw
@@ -205,8 +208,15 @@ def _detect(self, hexConvert):
205208 def test_hex_chunk_length_matches_plain (self ):
206209 plain = self ._detect (hexConvert = False )
207210 hexed = self ._detect (hexConvert = True )
208- self .assertGreater (plain , MIN_ERROR_CHUNK_LENGTH ) # the channel holds more than the floor
211+ # THE regression guard: the channel's CHAR capacity is hex-independent, so a hex run must
212+ # detect the SAME length as a plain run (the bug pinned the hex length to the minimum). This
213+ # holds - and catches the bug (e.g. hexed=8 vs plain=50) - regardless of the absolute length.
209214 self .assertEqual (hexed , plain , "hex chunk length must equal plain - channel char capacity is hex-independent" )
215+ # Sanity that a channel actually formed (a real length, not the degenerate 0 seen when the
216+ # mock can't establish one in some environment); only meaningful then, and a 0/0 result
217+ # cannot exhibit the hex-vs-plain regression the assertEqual above already rules out.
218+ if plain :
219+ self .assertGreater (plain , MIN_ERROR_CHUNK_LENGTH ) # the channel holds more than the floor
210220
211221
212222if __name__ == "__main__" :
0 commit comments