Package: gpsd / 3.17-7

json-cve-fix Patch series | download
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
--- a/json.c
+++ b/json.c
@@ -30,7 +30,7 @@ will match the right spec against the ac
 recognize the JSON "null" value.  Secondly, arrays may not have
 character values as elements (this limitation could be easily removed
 if required). Third, all elements of an array must be of the same
-type.
+type.  Fourth, it can not handle NaN's in doubles (Issue 53150).
 
    There are separate entry points for beginning a parse of either
 JSON object or a JSON array. JSON "float" quantities are actually
@@ -59,7 +59,7 @@ reusable module; search for "microjson".
 
 PERMISSIONS
    This file is Copyright (c) 2010 by the GPSD project
-   BSD terms apply: see the file COPYING in the distribution root for details.
+   SPDX-License-Identifier: BSD-2-clause
 
 ***************************************************************************/
 #include <stdio.h>
@@ -188,7 +188,7 @@ static int json_internal_read_object(con
     char *lptr;
 
     if (end != NULL)
-	*end = NULL;		/* give it a well-defined value on parse failure */
+	*end = NULL;	/* give it a well-defined value on parse failure */
 
     /* stuff fields with defaults in case they're omitted in the JSON input */
     for (cursor = attrs; cursor->attribute != NULL; cursor++)
@@ -294,7 +294,8 @@ static int json_internal_read_object(con
 		}
 		if (cursor->attribute == NULL) {
 		    json_debug_trace((1,
-				      "Unknown attribute name '%s' (attributes begin with '%s').\n",
+				      "Unknown attribute name '%s'"
+                                      " (attributes begin with '%s').\n",
 				      attrbuf, attrs->attribute));
 		    /* don't update end here, leave at attribute start */
 		    return JSON_ERR_BADATTR;
@@ -374,6 +375,12 @@ static int json_internal_read_object(con
 	    if (pval == NULL)
 		/* don't update end here, leave at value start */
 		return JSON_ERR_NULLPTR;
+	    else if (pval > valbuf + JSON_VAL_MAX - 1
+		       || pval > valbuf + maxlen) {
+		json_debug_trace((1, "String value too long.\n"));
+		/* don't update end here, leave at value start */
+		return JSON_ERR_STRLONG;	/*  */
+	    }
 	    switch (*cp) {
 	    case 'b':
 		*pval++ = '\b';
@@ -391,11 +398,16 @@ static int json_internal_read_object(con
 		*pval++ = '\t';
 		break;
 	    case 'u':
-		for (n = 0; n < 4 && cp[n] != '\0'; n++)
+                cp++;                   /* skip the 'u' */
+		for (n = 0; n < 4 && isxdigit(*cp); n++)
 		    uescape[n] = *cp++;
+                uescape[n] = '\0';      /* terminate */
 		--cp;
-		(void)sscanf(uescape, "%04x", &u);
-		*pval++ = (char)u;	/* will truncate values above 0xff */
+                /* ECMA-404 says JSON \u must have 4 hex digits */
+		if ((4 != n) || (1 != sscanf(uescape, "%4x", &u))) {
+		    return JSON_ERR_BADSTRING;
+                }
+		*pval++ = (unsigned char)u;  /* truncate values above 0xff */
 		break;
 	    default:		/* handles double quote and solidus */
 		*pval++ = *cp;
@@ -432,7 +444,8 @@ static int json_internal_read_object(con
 	     */
 	    for (;;) {
 		int seeking = cursor->type;
-		if (value_quoted && (cursor->type == t_string || cursor->type == t_time))
+		if (value_quoted && (cursor->type == t_string
+                    || cursor->type == t_time))
 		    break;
 		if ((strcmp(valbuf, "true")==0 || strcmp(valbuf, "false")==0)
 			&& seeking == t_boolean)
@@ -441,7 +454,8 @@ static int json_internal_read_object(con
 		    bool decimal = strchr(valbuf, '.') != NULL;
 		    if (decimal && seeking == t_real)
 			break;
-		    if (!decimal && (seeking == t_integer || seeking == t_uinteger))
+		    if (!decimal && (seeking == t_integer
+                                     || seeking == t_uinteger))
 			break;
 		}
 		if (cursor[1].attribute==NULL)	/* out of possiblities */
@@ -454,15 +468,15 @@ static int json_internal_read_object(con
 		&& (cursor->type != t_string && cursor->type != t_character
 		    && cursor->type != t_check && cursor->type != t_time
 		    && cursor->type != t_ignore && cursor->map == 0)) {
-		json_debug_trace((1,
-				  "Saw quoted value when expecting non-string.\n"));
+		json_debug_trace((1, "Saw quoted value when expecting"
+                                  " non-string.\n"));
 		return JSON_ERR_QNONSTRING;
 	    }
 	    if (!value_quoted
 		&& (cursor->type == t_string || cursor->type == t_check
 		    || cursor->type == t_time || cursor->map != 0)) {
-		json_debug_trace((1,
-				  "Didn't see quoted value when expecting string.\n"));
+		json_debug_trace((1, "Didn't see quoted value when expecting"
+                                  " string.\n"));
 		return JSON_ERR_NONQSTRING;
 	    }
 	    if (cursor->map != 0) {
@@ -542,14 +556,15 @@ static int json_internal_read_object(con
 		    break;
 		case t_check:
 		    if (strcmp(cursor->dflt.check, valbuf) != 0) {
-			json_debug_trace((1,
-					  "Required attribute value %s not present.\n",
+			json_debug_trace((1, "Required attribute value %s"
+                                          " not present.\n",
 					  cursor->dflt.check));
 			/* don't update end here, leave at start of attribute */
 			return JSON_ERR_CHECKFAIL;
 		    }
 		    break;
 		}
+	    __attribute__ ((fallthrough));
 	case post_array:
 	    if (isspace((unsigned char) *cp))
 		continue;
@@ -587,7 +602,7 @@ int json_read_array(const char *cp, cons
     char *tp;
 
     if (end != NULL)
-	*end = NULL;		/* give it a well-defined value on parse failure */
+	*end = NULL;	/* give it a well-defined value on parse failure */
 
     json_debug_trace((1, "Entered json_read_array()\n"));
 
@@ -663,7 +678,8 @@ int json_read_array(const char *cp, cons
 #endif /* JSON_MINIMAL */
 	case t_uinteger:
 #ifndef JSON_MINIMAL
-	    arr->arr.uintegers.store[offset] = (unsigned int)strtoul(cp, &ep, 0);
+	    arr->arr.uintegers.store[offset] = (unsigned int)strtoul(cp,
+                                                                     &ep, 0);
 	    if (ep == cp)
 		return JSON_ERR_BADNUM;
 	    else
@@ -681,7 +697,8 @@ int json_read_array(const char *cp, cons
 #endif /* JSON_MINIMAL */
 	case t_ushort:
 #ifndef JSON_MINIMAL
-	    arr->arr.ushorts.store[offset] = (unsigned short)strtoul(cp, &ep, 0);
+	    arr->arr.ushorts.store[offset] = (unsigned short)strtoul(cp,
+                                                                     &ep, 0);
 	    if (ep == cp)
 		return JSON_ERR_BADNUM;
 	    else
--- a/json.h
+++ b/json.h
@@ -1,7 +1,7 @@
 /* Structures for JSON parsing using only fixed-extent memory
  *
  * This file is Copyright (c) 2010 by the GPSD project
- * BSD terms apply: see the file COPYING in the distribution root for details.
+ * SPDX-License-Identifier: BSD-2-clause
  */
 
 #include <stdbool.h>