annotate mercurial/mpatch.c @ 39018:e793e11e1462

changegroup: introduce requests to define delta generation Currently, we iterate through each revision we will be producing a delta for then call into 1 of 2 functions for generating that delta. Deltas are emitted as we iterate. A problem with this model is that revision generation is tightly coupled to the changegroup code. And the storage layer needs to expose APIs like deltaparent() so changegroup delta generation can produce a delta with that knowledge. Another problem is that in this model, deltas can only be produced sequentially after the previous delta was produced and emitted. Some storage backends might be capable of producing deltas in parallel (e.g. if the changegroup deltas are cached somewhere). This commit aims to solve these problems by turning delta generation into a 2 phase implementation where the first phase determines info about all the deltas that need to be generated and the 2nd phase resolves those deltas. We introduce a "revisiondeltarequest" object that holds data about a to-be-generated delta. We perform a full pass over all revisions whose delta is to be generated and generate a "revisiondeltarequest" for each. Then we iterate over the "revisiondeltarequest" instances and derive a "revisiondelta" for each. This patch was quite large. In order to avoid even more churn, aspects of the implementation are less than ideal. e.g. we're recording revision numbers instead of nodes in a few places and we don't yet have a formal API for resolving an iterable of revisiondeltarequest instances. Things will be improved in subsequent commits. Unfortunately, this commit reduces performance substantially. For `hg perfchangegroupchangelog` on my hg repo: ! wall 1.512607 comb 1.510000 user 1.490000 sys 0.020000 (best of 7) ! wall 2.150863 comb 2.150000 user 2.150000 sys 0.000000 (best of 5) And for `hg bundle -t none-v2 -a` for the mozilla-unified repo: 178.32user 4.22system 3:02.59elapsed 190.97user 4.17system 3:15.19elapsed Some of this was attributed to changelog slowdown. `hg perfchangegroupchangelog` on mozilla-unified: ! wall 21.688715 comb 21.690000 user 21.570000 sys 0.120000 (best of 3) ! wall 25.683659 comb 25.680000 user 25.540000 sys 0.140000 (best of 3) Profiling seems to reveal that the changelog slowdown is due to reading changelog revisions multiple times. First in the linknode callback to resolve the set of files changed. Second in the delta generation. Before, we likely had hit the last revision cache in the revlog when doing delta generation since we performed that immediately after performing the linknode callback. I'm not exactly sure where the other ~8s are being spent. It might be from overhead of constructing a few million revisiondeltarequest objects. I'm OK with the regression for now because it is in service of a larger cause (storage abstraction). I'll try to profile later and claw back the performance. Differential Revision: https://phab.mercurial-scm.org/D4215
author Gregory Szorc <gregory.szorc@gmail.com>
date Thu, 09 Aug 2018 09:28:26 -0700
parents 9c5ced5276d6
children 763b45bc4483
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
1 /*
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
2 mpatch.c - efficient binary patching for Mercurial
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
3
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
4 This implements a patch algorithm that's O(m + nlog n) where m is the
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
5 size of the output and n is the number of patches.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
6
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
7 Given a list of binary patches, it unpacks each into a hunk list,
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
8 then combines the hunk lists with a treewise recursion to form a
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
9 single hunk list. This hunk list is then applied to the original
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
10 text.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
11
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
12 The text (or binary) fragments are copied directly from their source
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
13 Python objects into a preallocated output string to avoid the
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
14 allocation of intermediate Python objects. Working memory is about 2x
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
15 the total number of hunks.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
16
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2543
diff changeset
17 Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
18
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
19 This software may be used and distributed according to the terms
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
20 of the GNU General Public License, incorporated herein by reference.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
21 */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
22
38190
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
23 #include <limits.h>
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
24 #include <stdlib.h>
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
25 #include <string.h>
2468
1ac0574f1768 mac os x: fixes for 10.2 from chris monson <monpublic@gmail.com>
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2083
diff changeset
26
29444
284d742e5611 internals: move the bitmanipulation routines into its own file
Maciej Fijalkowski <fijall@gmail.com>
parents: 28782
diff changeset
27 #include "bitmanipulation.h"
29691
e9a0bcc9314d mpatch: change Py_ssize_t to ssize_t in places that will be later copied
Maciej Fijalkowski <fijall@gmail.com>
parents: 29444
diff changeset
28 #include "compat.h"
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
29 #include "mpatch.h"
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
30
38190
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
31 /* VC9 doesn't include bool and lacks stdbool.h based on cext/util.h */
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
32 #if defined(_MSC_VER) || __STDC_VERSION__ < 199901L
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
33 #define true 1
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
34 #define false 0
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
35 typedef unsigned char bool;
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
36 #else
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
37 #include <stdbool.h>
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
38 #endif
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
39
29741
9a1685c70db4 mpatch: change lalloc() to local function
Yuya Nishihara <yuya@tcha.org>
parents: 29740
diff changeset
40 static struct mpatch_flist *lalloc(ssize_t size)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
41 {
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
42 struct mpatch_flist *a = NULL;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
43
3138
cc856c4d91ca mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents: 2859
diff changeset
44 if (size < 1)
cc856c4d91ca mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents: 2859
diff changeset
45 size = 1;
cc856c4d91ca mpatch: Fix for malloc corner case on AIX
Matt Mackall <mpm@selenic.com>
parents: 2859
diff changeset
46
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
47 a = (struct mpatch_flist *)malloc(sizeof(struct mpatch_flist));
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
48 if (a) {
34633
347c0f4232e1 mpatch: re-wrap wide line with clang-format
Augie Fackler <augie@google.com>
parents: 29749
diff changeset
49 a->base = (struct mpatch_frag *)malloc(
347c0f4232e1 mpatch: re-wrap wide line with clang-format
Augie Fackler <augie@google.com>
parents: 29749
diff changeset
50 sizeof(struct mpatch_frag) * size);
2048
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
51 if (a->base) {
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
52 a->head = a->tail = a->base;
2048
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
53 return a;
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
54 }
8f9660c568b8 Set correct exception for another possible malloc error in mpatch.c
Thomas Arendsen Hein <thomas@intevation.de>
parents: 1978
diff changeset
55 free(a);
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
56 }
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
57 return NULL;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
58 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
59
29693
b9b9f9a92481 mpatch: split mpatch into two files
Maciej Fijalkowski <fijall@gmail.com>
parents: 29692
diff changeset
60 void mpatch_lfree(struct mpatch_flist *a)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
61 {
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
62 if (a) {
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
63 free(a->base);
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
64 free(a);
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
65 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
66 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
67
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
68 static ssize_t lsize(struct mpatch_flist *a)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
69 {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
70 return a->tail - a->head;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
71 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
72
38190
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
73 /* add helper to add src and *dest iff it won't overflow */
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
74 static inline bool safeadd(int src, int *dest)
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
75 {
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
76 if ((src > 0) == (*dest > 0)) {
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
77 if (*dest > 0) {
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
78 if (src > (INT_MAX - *dest)) {
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
79 return false;
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
80 }
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
81 } else {
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
82 if (src < (INT_MIN - *dest)) {
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
83 return false;
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
84 }
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
85 }
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
86 }
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
87 *dest += src;
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
88 return true;
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
89 }
1ec4cb8cbc87 mpatch: introduce a safeadd() helper to work around UB int overflow
Augie Fackler <augie@google.com>
parents: 38189
diff changeset
90
38191
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
91 /* subtract src from dest and store result in dest */
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
92 static inline bool safesub(int src, int *dest)
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
93 {
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
94 if (((src > 0) && (*dest < INT_MIN + src)) ||
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
95 ((src < 0) && (*dest > INT_MAX + src))) {
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
96 return false;
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
97 }
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
98 *dest -= src;
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
99 return true;
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
100 }
b8b253aec953 mpatch: introduce a safesub() helper as well
Augie Fackler <augie@google.com>
parents: 38190
diff changeset
101
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
102 /* move hunks in source that are less cut to dest, compensating
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
103 for changes in offset. the last hunk may be split if necessary.
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
104 */
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
105 static int gather(struct mpatch_flist *dest, struct mpatch_flist *src, int cut,
34800
761355833867 mpatch: reformat function prototypes with clang-format
Augie Fackler <augie@google.com>
parents: 34634
diff changeset
106 int offset)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
107 {
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
108 struct mpatch_frag *d = dest->tail, *s = src->head;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
109 int postend, c, l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
110
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
111 while (s != src->tail) {
38192
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
112 int soffset = s->start;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
113 if (!safeadd(offset, &soffset))
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
114 break; /* add would overflow, oh well */
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
115 if (soffset >= cut)
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
116 break; /* we've gone far enough */
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
117
38192
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
118 postend = offset;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
119 if (!safeadd(s->start, &postend) ||
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
120 !safeadd(s->len, &postend)) {
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
121 break;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
122 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
123 if (postend <= cut) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
124 /* save this hunk */
38192
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
125 int tmp = s->start;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
126 if (!safesub(s->end, &tmp)) {
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
127 break;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
128 }
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
129 if (!safeadd(s->len, &tmp)) {
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
130 break;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
131 }
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
132 if (!safeadd(tmp, &offset)) {
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
133 break; /* add would overflow, oh well */
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
134 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
135 *d++ = *s++;
34634
2e08b69bcd29 mpatch: reflow two oddly formatted else blocks with clang-format
Augie Fackler <augie@google.com>
parents: 34633
diff changeset
136 } else {
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
137 /* break up this hunk */
38192
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
138 c = cut;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
139 if (!safesub(offset, &c)) {
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
140 break;
0b208c13781c mpatch: fix UB in int overflows in gather() (SEC)
Augie Fackler <augie@google.com>
parents: 38191
diff changeset
141 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
142 if (s->end < c)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
143 c = s->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
144 l = cut - offset - s->start;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
145 if (s->len < l)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
146 l = s->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
147
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
148 offset += s->start + l - c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
149
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
150 d->start = s->start;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
151 d->end = c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
152 d->len = l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
153 d->data = s->data;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
154 d++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
155 s->start = c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
156 s->len = s->len - l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
157 s->data = s->data + l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
158
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
159 break;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
160 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
161 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
162
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
163 dest->tail = d;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
164 src->head = s;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
165 return offset;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
166 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
167
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
168 /* like gather, but with no output list */
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
169 static int discard(struct mpatch_flist *src, int cut, int offset)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
170 {
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
171 struct mpatch_frag *s = src->head;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
172 int postend, c, l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
173
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
174 while (s != src->tail) {
38193
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
175 int cmpcut = s->start;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
176 if (!safeadd(offset, &cmpcut)) {
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
177 break;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
178 }
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
179 if (cmpcut >= cut)
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
180 break;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
181
38193
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
182 postend = offset;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
183 if (!safeadd(s->start, &postend)) {
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
184 break;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
185 }
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
186 if (!safeadd(s->len, &postend)) {
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
187 break;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
188 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
189 if (postend <= cut) {
38193
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
190 /* do the subtraction first to avoid UB integer overflow
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
191 */
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
192 int tmp = s->start;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
193 if (!safesub(s->end, &tmp)) {
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
194 break;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
195 }
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
196 if (!safeadd(s->len, &tmp)) {
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
197 break;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
198 }
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
199 if (!safeadd(tmp, &offset)) {
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
200 break;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
201 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
202 s++;
34634
2e08b69bcd29 mpatch: reflow two oddly formatted else blocks with clang-format
Augie Fackler <augie@google.com>
parents: 34633
diff changeset
203 } else {
38193
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
204 c = cut;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
205 if (!safesub(offset, &c)) {
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
206 break;
7f22ef3c0ee7 mpatch: fix UB integer overflows in discard() (SEC)
Augie Fackler <augie@google.com>
parents: 38192
diff changeset
207 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
208 if (s->end < c)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
209 c = s->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
210 l = cut - offset - s->start;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
211 if (s->len < l)
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
212 l = s->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
213
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
214 offset += s->start + l - c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
215 s->start = c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
216 s->len = s->len - l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
217 s->data = s->data + l;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
218
82
7ed96baa7caa Gotos are embarrassing.
mpm@selenic.com
parents: 72
diff changeset
219 break;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
220 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
221 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
222
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
223 src->head = s;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
224 return offset;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
225 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
226
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
227 /* combine hunk lists a and b, while adjusting b for offset changes in a/
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
228 this deletes a and b and returns the resultant list. */
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
229 static struct mpatch_flist *combine(struct mpatch_flist *a,
34800
761355833867 mpatch: reformat function prototypes with clang-format
Augie Fackler <augie@google.com>
parents: 34634
diff changeset
230 struct mpatch_flist *b)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
231 {
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
232 struct mpatch_flist *c = NULL;
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
233 struct mpatch_frag *bh, *ct;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
234 int offset = 0, post;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
235
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
236 if (a && b)
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
237 c = lalloc((lsize(a) + lsize(b)) * 2);
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
238
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
239 if (c) {
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
240
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
241 for (bh = b->head; bh != b->tail; bh++) {
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
242 /* save old hunks */
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
243 offset = gather(c, a, bh->start, offset);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
244
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
245 /* discard replaced hunks */
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
246 post = discard(a, bh->end, offset);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
247
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
248 /* insert new hunk */
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
249 ct = c->tail;
38195
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
250 ct->start = bh->start;
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
251 ct->end = bh->end;
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
252 if (!safesub(offset, &(ct->start)) ||
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
253 !safesub(post, &(ct->end))) {
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
254 /* It was already possible to exit
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
255 * this function with a return value
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
256 * of NULL before the safesub()s were
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
257 * added, so this should be fine. */
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
258 mpatch_lfree(c);
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
259 c = NULL;
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
260 goto done;
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
261 }
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
262 ct->len = bh->len;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
263 ct->data = bh->data;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
264 c->tail++;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
265 offset = post;
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
266 }
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
267
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
268 /* hold on to tail from a */
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
269 memcpy(c->tail, a->head, sizeof(struct mpatch_frag) * lsize(a));
128
d6afb6dbf9f2 Add safety checking to mpatch
mpm@selenic.com
parents: 82
diff changeset
270 c->tail += lsize(a);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
271 }
38195
9c5ced5276d6 mpatch: avoid integer overflow in combine() (SEC)
Augie Fackler <augie@google.com>
parents: 38194
diff changeset
272 done:
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
273 mpatch_lfree(a);
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
274 mpatch_lfree(b);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
275 return c;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
276 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
277
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
278 /* decode a binary patch into a hunk list */
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
279 int mpatch_decode(const char *bin, ssize_t len, struct mpatch_flist **res)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
280 {
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
281 struct mpatch_flist *l;
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
282 struct mpatch_frag *lt;
20167
09e41ac6289d mpatch: rewrite pointer overflow checks
Matt Mackall <mpm@selenic.com>
parents: 16758
diff changeset
283 int pos = 0;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
284
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
285 /* assume worst case size, we won't have many of these lists */
28656
b6ed2505d6cf parsers: fix list sizing rounding error (SEC)
Matt Mackall <mpm@selenic.com>
parents: 20167
diff changeset
286 l = lalloc(len / 12 + 1);
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
287 if (!l)
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
288 return MPATCH_ERR_NO_MEM;
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
289
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
290 lt = l->tail;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
291
38187
90a274965de7 mpatch: be more careful about parsing binary patch data (SEC)
Augie Fackler <augie@google.com>
parents: 34801
diff changeset
292 /* We check against len-11 to ensure we have at least 12 bytes
90a274965de7 mpatch: be more careful about parsing binary patch data (SEC)
Augie Fackler <augie@google.com>
parents: 34801
diff changeset
293 left in the patch so we can read our three be32s out of it. */
90a274965de7 mpatch: be more careful about parsing binary patch data (SEC)
Augie Fackler <augie@google.com>
parents: 34801
diff changeset
294 while (pos >= 0 && pos < (len - 11)) {
20167
09e41ac6289d mpatch: rewrite pointer overflow checks
Matt Mackall <mpm@selenic.com>
parents: 16758
diff changeset
295 lt->start = getbe32(bin + pos);
09e41ac6289d mpatch: rewrite pointer overflow checks
Matt Mackall <mpm@selenic.com>
parents: 16758
diff changeset
296 lt->end = getbe32(bin + pos + 4);
09e41ac6289d mpatch: rewrite pointer overflow checks
Matt Mackall <mpm@selenic.com>
parents: 16758
diff changeset
297 lt->len = getbe32(bin + pos + 8);
38194
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
298 if (lt->start < 0 || lt->start > lt->end || lt->len < 0)
28657
b9714d958e89 parsers: detect short records (SEC)
Matt Mackall <mpm@selenic.com>
parents: 28656
diff changeset
299 break; /* sanity check */
38194
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
300 if (!safeadd(12, &pos)) {
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
301 break;
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
302 }
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
303 lt->data = bin + pos;
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
304 if (!safeadd(lt->len, &pos)) {
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
305 break;
59837a16896d mpatch: avoid integer overflow in mpatch_decode (SEC)
Augie Fackler <augie@google.com>
parents: 38193
diff changeset
306 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
307 lt++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
308 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
309
20167
09e41ac6289d mpatch: rewrite pointer overflow checks
Matt Mackall <mpm@selenic.com>
parents: 16758
diff changeset
310 if (pos != len) {
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
311 mpatch_lfree(l);
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
312 return MPATCH_ERR_CANNOT_BE_DECODED;
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
313 }
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
314
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
315 l->tail = lt;
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
316 *res = l;
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
317 return 0;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
318 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
319
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
320 /* calculate the size of resultant text */
29693
b9b9f9a92481 mpatch: split mpatch into two files
Maciej Fijalkowski <fijall@gmail.com>
parents: 29692
diff changeset
321 ssize_t mpatch_calcsize(ssize_t len, struct mpatch_flist *l)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
322 {
29691
e9a0bcc9314d mpatch: change Py_ssize_t to ssize_t in places that will be later copied
Maciej Fijalkowski <fijall@gmail.com>
parents: 29444
diff changeset
323 ssize_t outlen = 0, last = 0;
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
324 struct mpatch_frag *f = l->head;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
325
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
326 while (f != l->tail) {
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
327 if (f->start < last || f->end > len) {
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
328 return MPATCH_ERR_INVALID_PATCH;
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
329 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
330 outlen += f->start - last;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
331 last = f->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
332 outlen += f->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
333 f++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
334 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
335
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
336 outlen += len - last;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
337 return outlen;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
338 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
339
29693
b9b9f9a92481 mpatch: split mpatch into two files
Maciej Fijalkowski <fijall@gmail.com>
parents: 29692
diff changeset
340 int mpatch_apply(char *buf, const char *orig, ssize_t len,
34800
761355833867 mpatch: reformat function prototypes with clang-format
Augie Fackler <augie@google.com>
parents: 34634
diff changeset
341 struct mpatch_flist *l)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
342 {
29692
6b3a8d034b69 mpatch: provide things that will be exported later with a prefixed name
Maciej Fijalkowski <fijall@gmail.com>
parents: 29691
diff changeset
343 struct mpatch_frag *f = l->head;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
344 int last = 0;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
345 char *p = buf;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
346
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
347 while (f != l->tail) {
38189
faa924469635 mpatch: ensure fragment start isn't past the end of orig (SEC)
Augie Fackler <augie@google.com>
parents: 38188
diff changeset
348 if (f->start < last || f->start > len || f->end > len ||
faa924469635 mpatch: ensure fragment start isn't past the end of orig (SEC)
Augie Fackler <augie@google.com>
parents: 38188
diff changeset
349 last < 0) {
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
350 return MPATCH_ERR_INVALID_PATCH;
1722
681c5c211b92 catch errors and throw exception with invalid binary patch data
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 597
diff changeset
351 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
352 memcpy(p, orig + last, f->start - last);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
353 p += f->start - last;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
354 memcpy(p, f->data, f->len);
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
355 last = f->end;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
356 p += f->len;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
357 f++;
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
358 }
38188
1acfc35d478c mpatch: protect against underflow in mpatch_apply (SEC)
Augie Fackler <augie@google.com>
parents: 38187
diff changeset
359 if (last < 0) {
1acfc35d478c mpatch: protect against underflow in mpatch_apply (SEC)
Augie Fackler <augie@google.com>
parents: 38187
diff changeset
360 return MPATCH_ERR_INVALID_PATCH;
1acfc35d478c mpatch: protect against underflow in mpatch_apply (SEC)
Augie Fackler <augie@google.com>
parents: 38187
diff changeset
361 }
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
362 memcpy(p, orig + last, len - last);
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
363 return 0;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
364 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
365
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
366 /* recursively generate a patch of all bins between start and end */
34800
761355833867 mpatch: reformat function prototypes with clang-format
Augie Fackler <augie@google.com>
parents: 34634
diff changeset
367 struct mpatch_flist *
761355833867 mpatch: reformat function prototypes with clang-format
Augie Fackler <augie@google.com>
parents: 34634
diff changeset
368 mpatch_fold(void *bins, struct mpatch_flist *(*get_next_item)(void *, ssize_t),
761355833867 mpatch: reformat function prototypes with clang-format
Augie Fackler <augie@google.com>
parents: 34634
diff changeset
369 ssize_t start, ssize_t end)
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
370 {
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
371 ssize_t len;
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
372
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
373 if (start + 1 == end) {
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
374 /* trivial case, output a decoded list */
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
375 return get_next_item(bins, start);
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
376 }
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
377
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
378 /* divide and conquer, memory management is elsewhere */
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
379 len = (end - start) / 2;
29694
55dd12204b8e mpatch: remove dependency on Python.h in mpatch.c
Maciej Fijalkowski <fijall@gmail.com>
parents: 29693
diff changeset
380 return combine(mpatch_fold(bins, get_next_item, start, start + len),
34801
1f4249c764f1 mpatch: switch alignment of wrapped line from tab to spaces with clang-format
Augie Fackler <augie@google.com>
parents: 34800
diff changeset
381 mpatch_fold(bins, get_next_item, start + len, end));
72
4a6ab4d80dc4 Add an O(m + nlog n) patching extension
mpm@selenic.com
parents:
diff changeset
382 }