Skip to content

Commit 096b779

Browse files
committed
Fix parsing (patch chunks are driven by their defined length and nothing else)
1 parent af13bfa commit 096b779

1 file changed

Lines changed: 24 additions & 11 deletions

File tree

src/patch.ml

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,33 @@ let count_to_sl_sl data =
116116
else
117117
None
118118

119-
let sort_into_bags dir mine their m_nl t_nl str =
119+
let sort_into_bags ~counter:(mine_len, their_len) dir mine their m_nl t_nl str =
120120
if String.length str = 0 then
121+
failwith "invalid patch (empty line)"
122+
else if mine_len = 0 && their_len = 0 && String.get str 0 <> '\\' then
121123
None
122124
else match String.get str 0, String.slice ~start:1 str with
123125
| ' ', data ->
124126
if m_nl || t_nl then
125127
failwith "\"no newline at the end of file\" is not at the end of the file";
126-
Some (`Both, (data :: mine), (data :: their), m_nl, t_nl)
128+
if mine_len = 0 || their_len = 0 then
129+
failwith "invalid patch (both size exhausted)";
130+
let counter = (mine_len - 1, their_len - 1) in
131+
Some (counter, `Both, (data :: mine), (data :: their), m_nl, t_nl)
127132
| '+', data ->
128133
if t_nl then
129134
failwith "\"no newline at the end of file\" is not at the end of the file";
130-
Some (`Their, mine, (data :: their), m_nl, t_nl)
135+
if their_len = 0 then
136+
failwith "invalid patch (+ size exhausted)";
137+
let counter = (mine_len, their_len - 1) in
138+
Some (counter, `Their, mine, (data :: their), m_nl, t_nl)
131139
| '-', data ->
132140
if m_nl then
133141
failwith "\"no newline at the end of file\" is not at the end of the file";
134-
Some (`Mine, (data :: mine), their, m_nl, t_nl)
142+
if mine_len = 0 then
143+
failwith "invalid patch (- size exhausted)";
144+
let counter = (mine_len - 1, their_len) in
145+
Some (counter, `Mine, (data :: mine), their, m_nl, t_nl)
135146
| '\\', _data ->
136147
(* NOTE: Any line starting with '\' is taken as if it was
137148
'\ No newline at end of file' by GNU patch so we do the same *)
@@ -143,20 +154,22 @@ let sort_into_bags dir mine their m_nl t_nl str =
143154
| `Mine -> true, t_nl
144155
| `Their -> m_nl, true
145156
in
146-
Some (dir, mine, their, my_nl, their_nl)
147-
| _ -> None
157+
let counter = (mine_len, their_len) in
158+
Some (counter, dir, mine, their, my_nl, their_nl)
159+
| _ -> failwith "invalid patch (unknown character)"
148160

149161
let to_hunk count data mine_no_nl their_no_nl =
150162
match count_to_sl_sl count with
151163
| None -> None, mine_no_nl, their_no_nl, count :: data
152164
| Some ((mine_start, mine_len), (their_start, their_len)) ->
153-
let rec step dir mine their mine_no_nl their_no_nl = function
154-
| [] -> (List.rev mine, List.rev their, mine_no_nl, their_no_nl, [])
155-
| x::xs -> match sort_into_bags dir mine their mine_no_nl their_no_nl x with
156-
| Some (dir, mine, their, mine_no_nl', their_no_nl') -> step dir mine their mine_no_nl' their_no_nl' xs
165+
let counter = (mine_len, their_len) in
166+
let rec step ~counter dir mine their mine_no_nl their_no_nl = function
167+
| [] | [""] -> (List.rev mine, List.rev their, mine_no_nl, their_no_nl, [])
168+
| x::xs -> match sort_into_bags ~counter dir mine their mine_no_nl their_no_nl x with
169+
| Some (counter, dir, mine, their, mine_no_nl', their_no_nl') -> step ~counter dir mine their mine_no_nl' their_no_nl' xs
157170
| None -> (List.rev mine, List.rev their, mine_no_nl, their_no_nl, x :: xs)
158171
in
159-
let mine, their, mine_no_nl, their_no_nl, rest = step `Both [] [] mine_no_nl their_no_nl data in
172+
let mine, their, mine_no_nl, their_no_nl, rest = step ~counter `Both [] [] mine_no_nl their_no_nl data in
160173
(Some { mine_start ; mine_len ; mine ; their_start ; their_len ; their }, mine_no_nl, their_no_nl, rest)
161174

162175
let rec to_hunks (mine_no_nl, their_no_nl, acc) = function

0 commit comments

Comments
 (0)