summary refs log tree commit diff
path: root/gnu/packages/patches/json-c-CVE-2020-12762.patch
blob: 80daa475e90fec978ded2449d112e33c3796f2e1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
https://github.com/json-c/json-c/pull/608
https://github.com/json-c/json-c/commit/5d6fa331418d49f1bd488553fd1cfa9ab023fabb.patch

From 5d6fa331418d49f1bd488553fd1cfa9ab023fabb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Thu, 14 May 2020 12:32:30 +0200
Subject: [PATCH] Fix CVE-2020-12762.

This commit is a squashed backport of the following commits
on the master branch:

  * 099016b7e8d70a6d5dd814e788bba08d33d48426
  * 77d935b7ae7871a1940cd827e850e6063044ec45
  * d07b91014986900a3a75f306d302e13e005e9d67
  * 519dfe1591d85432986f9762d41d1a883198c157
  * a59d5acfab4485d5133114df61785b1fc633e0c6
  * 26f080997d41cfdb17beab65e90c82217d0ac43b
---
 arraylist.c          |  3 +++
 linkhash.c           |  9 ++++++++-
 printbuf.c           | 18 ++++++++++++++++--
 tests/test4.c        | 29 +++++++++++++++++++++++++++++
 tests/test4.expected |  1 +
 5 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/arraylist.c b/arraylist.c
index 12ad8af6d3..e5524aca75 100644
--- a/arraylist.c
+++ b/arraylist.c
@@ -136,6 +136,9 @@ int array_list_del_idx(struct array_list *arr, size_t idx, size_t count)
 {
 	size_t i, stop;
 
+	/* Avoid overflow in calculation with large indices. */
+	if (idx > SIZE_T_MAX - count)
+		return -1;
 	stop = idx + count;
 	if (idx >= arr->length || stop > arr->length)
 		return -1;
diff --git a/linkhash.c b/linkhash.c
index 7ea58c0abf..b021ef10b0 100644
--- a/linkhash.c
+++ b/linkhash.c
@@ -12,6 +12,7 @@
 
 #include "config.h"
 
+#include <assert.h>
 #include <limits.h>
 #include <stdarg.h>
 #include <stddef.h>
@@ -499,6 +500,8 @@ struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *h
 	int i;
 	struct lh_table *t;
 
+	/* Allocate space for elements to avoid divisions by zero. */
+	assert(size > 0);
 	t = (struct lh_table *)calloc(1, sizeof(struct lh_table));
 	if (!t)
 		return NULL;
@@ -578,8 +581,12 @@ int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, con
 	unsigned long n;
 
 	if (t->count >= t->size * LH_LOAD_FACTOR)
-		if (lh_table_resize(t, t->size * 2) != 0)
+	{
+		/* Avoid signed integer overflow with large tables. */
+		int new_size = (t->size > INT_MAX / 2) ? INT_MAX : (t->size * 2);
+		if (t->size == INT_MAX || lh_table_resize(t, new_size) != 0)
 			return -1;
+	}
 
 	n = h % t->size;
 
diff --git a/printbuf.c b/printbuf.c
index 976c12dde5..f9b15b1191 100644
--- a/printbuf.c
+++ b/printbuf.c
@@ -15,6 +15,7 @@
 
 #include "config.h"
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -66,9 +67,16 @@ static int printbuf_extend(struct printbuf *p, int min_size)
 	if (p->size >= min_size)
 		return 0;
 
-	new_size = p->size * 2;
-	if (new_size < min_size + 8)
+	/* Prevent signed integer overflows with large buffers. */
+	if (min_size > INT_MAX - 8)
+		return -1;
+	if (p->size > INT_MAX / 2)
 		new_size = min_size + 8;
+	else {
+		new_size = p->size * 2;
+		if (new_size < min_size + 8)
+			new_size = min_size + 8;
+	}
 #ifdef PRINTBUF_DEBUG
 	MC_DEBUG("printbuf_memappend: realloc "
 	         "bpos=%d min_size=%d old_size=%d new_size=%d\n",
@@ -83,6 +91,9 @@ static int printbuf_extend(struct printbuf *p, int min_size)
 
 int printbuf_memappend(struct printbuf *p, const char *buf, int size)
 {
+	/* Prevent signed integer overflows with large buffers. */
+	if (size > INT_MAX - p->bpos - 1)
+		return -1;
 	if (p->size <= p->bpos + size + 1)
 	{
 		if (printbuf_extend(p, p->bpos + size + 1) < 0)
@@ -100,6 +111,9 @@ int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
 
 	if (offset == -1)
 		offset = pb->bpos;
+	/* Prevent signed integer overflows with large buffers. */
+	if (len > INT_MAX - offset)
+		return -1;
 	size_needed = offset + len;
 	if (pb->size < size_needed)
 	{
diff --git a/tests/test4.c b/tests/test4.c
index bd964ec789..288cec1792 100644
--- a/tests/test4.c
+++ b/tests/test4.c
@@ -3,12 +3,15 @@
  */
 
 #include "config.h"
+#include <assert.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "json_inttypes.h"
 #include "json_object.h"
 #include "json_tokener.h"
+#include "snprintf_compat.h"
 
 void print_hex(const char *s)
 {
@@ -24,6 +27,29 @@ void print_hex(const char *s)
 	putchar('\n');
 }
 
+static void test_lot_of_adds(void);
+static void test_lot_of_adds()
+{
+	int ii;
+	char key[50];
+	json_object *jobj = json_object_new_object();
+	assert(jobj != NULL);
+	for (ii = 0; ii < 500; ii++)
+	{
+		snprintf(key, sizeof(key), "k%d", ii);
+		json_object *iobj = json_object_new_int(ii);
+		assert(iobj != NULL);
+		if (json_object_object_add(jobj, key, iobj))
+		{
+			fprintf(stderr, "FAILED to add object #%d\n", ii);
+			abort();
+		}
+	}
+	printf("%s\n", json_object_to_json_string(jobj));
+	assert(json_object_object_length(jobj) == 500);
+	json_object_put(jobj);
+}
+
 int main(void)
 {
 	const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\"";
@@ -52,5 +78,8 @@ int main(void)
 		retval = 1;
 	}
 	json_object_put(parse_result);
+
+	test_lot_of_adds();
+
 	return retval;
 }
diff --git a/tests/test4.expected b/tests/test4.expected
index 68d4336d90..cb2744012b 100644
--- a/tests/test4.expected
+++ b/tests/test4.expected
@@ -1,3 +1,4 @@
 input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27"
 JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧
 PASS
+{ "k0": 0, "k1": 1, "k2": 2, "k3": 3, "k4": 4, "k5": 5, "k6": 6, "k7": 7, "k8": 8, "k9": 9, "k10": 10, "k11": 11, "k12": 12, "k13": 13, "k14": 14, "k15": 15, "k16": 16, "k17": 17, "k18": 18, "k19": 19, "k20": 20, "k21": 21, "k22": 22, "k23": 23, "k24": 24, "k25": 25, "k26": 26, "k27": 27, "k28": 28, "k29": 29, "k30": 30, "k31": 31, "k32": 32, "k33": 33, "k34": 34, "k35": 35, "k36": 36, "k37": 37, "k38": 38, "k39": 39, "k40": 40, "k41": 41, "k42": 42, "k43": 43, "k44": 44, "k45": 45, "k46": 46, "k47": 47, "k48": 48, "k49": 49, "k50": 50, "k51": 51, "k52": 52, "k53": 53, "k54": 54, "k55": 55, "k56": 56, "k57": 57, "k58": 58, "k59": 59, "k60": 60, "k61": 61, "k62": 62, "k63": 63, "k64": 64, "k65": 65, "k66": 66, "k67": 67, "k68": 68, "k69": 69, "k70": 70, "k71": 71, "k72": 72, "k73": 73, "k74": 74, "k75": 75, "k76": 76, "k77": 77, "k78": 78, "k79": 79, "k80": 80, "k81": 81, "k82": 82, "k83": 83, "k84": 84, "k85": 85, "k86": 86, "k87": 87, "k88": 88, "k89": 89, "k90": 90, "k91": 91, "k92": 92, "k93": 93, "k94": 94, "k95": 95, "k96": 96, "k97": 97, "k98": 98, "k99": 99, "k100": 100, "k101": 101, "k102": 102, "k103": 103, "k104": 104, "k105": 105, "k106": 106, "k107": 107, "k108": 108, "k109": 109, "k110": 110, "k111": 111, "k112": 112, "k113": 113, "k114": 114, "k115": 115, "k116": 116, "k117": 117, "k118": 118, "k119": 119, "k120": 120, "k121": 121, "k122": 122, "k123": 123, "k124": 124, "k125": 125, "k126": 126, "k127": 127, "k128": 128, "k129": 129, "k130": 130, "k131": 131, "k132": 132, "k133": 133, "k134": 134, "k135": 135, "k136": 136, "k137": 137, "k138": 138, "k139": 139, "k140": 140, "k141": 141, "k142": 142, "k143": 143, "k144": 144, "k145": 145, "k146": 146, "k147": 147, "k148": 148, "k149": 149, "k150": 150, "k151": 151, "k152": 152, "k153": 153, "k154": 154, "k155": 155, "k156": 156, "k157": 157, "k158": 158, "k159": 159, "k160": 160, "k161": 161, "k162": 162, "k163": 163, "k164": 164, "k165": 165, "k166": 166, "k167": 167, "k168": 168, "k169": 169, "k170": 170, "k171": 171, "k172": 172, "k173": 173, "k174": 174, "k175": 175, "k176": 176, "k177": 177, "k178": 178, "k179": 179, "k180": 180, "k181": 181, "k182": 182, "k183": 183, "k184": 184, "k185": 185, "k186": 186, "k187": 187, "k188": 188, "k189": 189, "k190": 190, "k191": 191, "k192": 192, "k193": 193, "k194": 194, "k195": 195, "k196": 196, "k197": 197, "k198": 198, "k199": 199, "k200": 200, "k201": 201, "k202": 202, "k203": 203, "k204": 204, "k205": 205, "k206": 206, "k207": 207, "k208": 208, "k209": 209, "k210": 210, "k211": 211, "k212": 212, "k213": 213, "k214": 214, "k215": 215, "k216": 216, "k217": 217, "k218": 218, "k219": 219, "k220": 220, "k221": 221, "k222": 222, "k223": 223, "k224": 224, "k225": 225, "k226": 226, "k227": 227, "k228": 228, "k229": 229, "k230": 230, "k231": 231, "k232": 232, "k233": 233, "k234": 234, "k235": 235, "k236": 236, "k237": 237, "k238": 238, "k239": 239, "k240": 240, "k241": 241, "k242": 242, "k243": 243, "k244": 244, "k245": 245, "k246": 246, "k247": 247, "k248": 248, "k249": 249, "k250": 250, "k251": 251, "k252": 252, "k253": 253, "k254": 254, "k255": 255, "k256": 256, "k257": 257, "k258": 258, "k259": 259, "k260": 260, "k261": 261, "k262": 262, "k263": 263, "k264": 264, "k265": 265, "k266": 266, "k267": 267, "k268": 268, "k269": 269, "k270": 270, "k271": 271, "k272": 272, "k273": 273, "k274": 274, "k275": 275, "k276": 276, "k277": 277, "k278": 278, "k279": 279, "k280": 280, "k281": 281, "k282": 282, "k283": 283, "k284": 284, "k285": 285, "k286": 286, "k287": 287, "k288": 288, "k289": 289, "k290": 290, "k291": 291, "k292": 292, "k293": 293, "k294": 294, "k295": 295, "k296": 296, "k297": 297, "k298": 298, "k299": 299, "k300": 300, "k301": 301, "k302": 302, "k303": 303, "k304": 304, "k305": 305, "k306": 306, "k307": 307, "k308": 308, "k309": 309, "k310": 310, "k311": 311, "k312": 312, "k313": 313, "k314": 314, "k315": 315, "k316": 316, "k317": 317, "k318": 318, "k319": 319, "k320": 320, "k321": 321, "k322": 322, "k323": 323, "k324": 324, "k325": 325, "k326": 326, "k327": 327, "k328": 328, "k329": 329, "k330": 330, "k331": 331, "k332": 332, "k333": 333, "k334": 334, "k335": 335, "k336": 336, "k337": 337, "k338": 338, "k339": 339, "k340": 340, "k341": 341, "k342": 342, "k343": 343, "k344": 344, "k345": 345, "k346": 346, "k347": 347, "k348": 348, "k349": 349, "k350": 350, "k351": 351, "k352": 352, "k353": 353, "k354": 354, "k355": 355, "k356": 356, "k357": 357, "k358": 358, "k359": 359, "k360": 360, "k361": 361, "k362": 362, "k363": 363, "k364": 364, "k365": 365, "k366": 366, "k367": 367, "k368": 368, "k369": 369, "k370": 370, "k371": 371, "k372": 372, "k373": 373, "k374": 374, "k375": 375, "k376": 376, "k377": 377, "k378": 378, "k379": 379, "k380": 380, "k381": 381, "k382": 382, "k383": 383, "k384": 384, "k385": 385, "k386": 386, "k387": 387, "k388": 388, "k389": 389, "k390": 390, "k391": 391, "k392": 392, "k393": 393, "k394": 394, "k395": 395, "k396": 396, "k397": 397, "k398": 398, "k399": 399, "k400": 400, "k401": 401, "k402": 402, "k403": 403, "k404": 404, "k405": 405, "k406": 406, "k407": 407, "k408": 408, "k409": 409, "k410": 410, "k411": 411, "k412": 412, "k413": 413, "k414": 414, "k415": 415, "k416": 416, "k417": 417, "k418": 418, "k419": 419, "k420": 420, "k421": 421, "k422": 422, "k423": 423, "k424": 424, "k425": 425, "k426": 426, "k427": 427, "k428": 428, "k429": 429, "k430": 430, "k431": 431, "k432": 432, "k433": 433, "k434": 434, "k435": 435, "k436": 436, "k437": 437, "k438": 438, "k439": 439, "k440": 440, "k441": 441, "k442": 442, "k443": 443, "k444": 444, "k445": 445, "k446": 446, "k447": 447, "k448": 448, "k449": 449, "k450": 450, "k451": 451, "k452": 452, "k453": 453, "k454": 454, "k455": 455, "k456": 456, "k457": 457, "k458": 458, "k459": 459, "k460": 460, "k461": 461, "k462": 462, "k463": 463, "k464": 464, "k465": 465, "k466": 466, "k467": 467, "k468": 468, "k469": 469, "k470": 470, "k471": 471, "k472": 472, "k473": 473, "k474": 474, "k475": 475, "k476": 476, "k477": 477, "k478": 478, "k479": 479, "k480": 480, "k481": 481, "k482": 482, "k483": 483, "k484": 484, "k485": 485, "k486": 486, "k487": 487, "k488": 488, "k489": 489, "k490": 490, "k491": 491, "k492": 492, "k493": 493, "k494": 494, "k495": 495, "k496": 496, "k497": 497, "k498": 498, "k499": 499 }