Selaa lähdekoodia

[eval] fix string operations on misaligned offsets

see #7247
Simon Krajewski 7 vuotta sitten
vanhempi
commit
8b8561e9a6

+ 14 - 36
src/macro/eval/evalStdLib.ml

@@ -1941,9 +1941,7 @@ module StdString = struct
 			else if this.sascii then
 				vint (Rope.search_forward_string (Lazy.force str.sstring) this.srope i)
 			else begin
-				let pat = Str.regexp (maybe_extend_ascii str) in
-				let s = Lazy.force this.sstring in
-				vint ((Str.search_forward pat s (i lsl 1)) lsr 1);
+				vint ((fst (find_substring this str false i)) lsr 1)
 			end
 		with Not_found ->
 			vint (-1)
@@ -1962,20 +1960,19 @@ module StdString = struct
 				let s = Lazy.force this.sstring in
 				if this.sascii then
 					vint (Str.search_backward (Str.regexp_string (Lazy.force str.sstring)) s i)
-				else begin
-					let pat = Str.regexp (maybe_extend_ascii str) in
-					vint ((Str.search_backward pat s (i lsl 1)) lsr 1);
-				end
+				else
+					vint ((fst (find_substring this str true (i lsl 1))) lsr 1)
 			end
 		with Not_found ->
 			vint (-1)
 	)
 
 	let split = vifun1 (fun vthis delimiter ->
-		let this = this vthis in
-		let ascii = this.sascii in
-		let this,s = this.srope,Lazy.force this.sstring in
-		let delimiter = Lazy.force (decode_vstring delimiter).sstring in
+		let this' = this vthis in
+		let ascii = this'.sascii in
+		let this,s = this'.srope,Lazy.force this'.sstring in
+		let delimiter' = (decode_vstring delimiter) in
+		let delimiter = Lazy.force delimiter'.sstring in
 		let l_delimiter = String.length delimiter in
 		let l_this = Rope.length this in
 		let encode_range pos length =
@@ -2000,36 +1997,17 @@ module StdString = struct
 		end else if l_delimiter > l_this then
 			encode_array [encode_range 0 (Rope.length this)]
 		else begin
-			let chr = delimiter.[0] in
 			let acc = DynArray.create () in
-			let rec loop k i =
-				try
-					if i > l_this - l_delimiter then raise Not_found;
-					let index = String.index_from s i chr in
-					let rec loop2 i2 =
-						if i2 = l_delimiter then true
-						else if String.unsafe_get s (index + i2) = String.unsafe_get delimiter i2 then loop2 (i2 + 1)
-						else false
-					in
-					if not (loop2 1) then
-						loop k (index + 1)
-					else begin
-						DynArray.add acc (encode_range k (index - k));
-						loop (index + l_delimiter) (index + l_delimiter)
-					end
-				with Not_found ->
-					DynArray.add acc (encode_range k (l_this - k))
-			in
-			let rec loop1 i =
+			let f = find_substring this' delimiter' false in
+			let rec loop i =
 				try
-					if i = l_this then raise Not_found;
-					let index = String.index_from s i chr in
-					DynArray.add acc (encode_range i (index - i));
-					loop1 (index + (l_delimiter lsl (if ascii then 0 else 1)))
+					let offset,next = f i in
+					DynArray.add acc (encode_range i (offset - i));
+					loop next;
 				with Not_found ->
 					DynArray.add acc (encode_range i (l_this - i))
 			in
-			if l_delimiter = 1 then loop1 0 else loop 0 0;
+			loop 0;
 			encode_array_instance (EvalArray.create (DynArray.to_array acc))
 		end
 	)

+ 31 - 0
src/macro/eval/evalString.ml

@@ -253,6 +253,37 @@ let from_char_code i =
 	end else
 		raise InvalidUnicodeChar
 
+let find_substring this sub reverse =
+	let l_this = Rope.length this.srope in
+	let s_this = Lazy.force this.sstring in
+	let s_sub = if not this.sascii then maybe_extend_ascii sub else Lazy.force sub.sstring in
+	let l_sub = String.length s_sub in
+	let rec scan i k =
+		if k = l_sub then true
+		else if String.unsafe_get s_this (i + k) = String.unsafe_get s_sub k then scan i (k + 1)
+		else false
+	in
+	let inc = if this.sascii then 1 else 2 in
+	if reverse then begin
+		let rec loop i =
+			if i < 0 then raise Not_found;
+			if scan i 0 then
+				i,i + l_sub
+			else
+				loop (i - inc)
+		in
+		loop
+	end else begin
+		let rec loop i =
+			if i > l_this - l_sub then raise Not_found;
+			if scan i 0 then
+				i,i + l_sub
+			else
+				loop (i + inc)
+		in
+		loop
+	end
+
 let get s =
 	let s' = Lazy.force s.sstring in
 	if s.sascii then s'

+ 7 - 1
tests/unit/src/unit/issues/Issue7247.hx

@@ -4,12 +4,18 @@ import unit.Test;
 class Issue7247 extends Test {
 
 	var str = "将一";
-	
+	var str2 = "将一\\";
+
 	function test() {
 		eq(str.indexOf("\\"),-1);
 		eq(str.lastIndexOf("\\"),-1);
 		eq(str.split("\\").length,1);
 		f( ~/\\/.match(str) );
+
+		eq(str2.indexOf("\\"), 2);
+		eq(str2.lastIndexOf("\\"), 2);
+		eq(str2.split("\\").length, 2);
+		t( ~/\\/.match(str2) );
 	}
 
 }