fe86db868fe2553e2446c62b065f43d6b036f61f
[asterisk/asterisk.git] / third-party / jansson / patches / 0029-json_pack-Improve-handling-of-formats-with-and.patch
1 From 5df5fc5b13cac5212482d36e7f3a78951782cfb5 Mon Sep 17 00:00:00 2001
2 From: Corey Farrell <git@cfware.com>
3 Date: Tue, 25 Sep 2018 14:31:56 -0400
4 Subject: [PATCH 29/30] json_pack: Improve handling of formats with '?' and
5  '*'.
6
7 Test updates have been removed for easier merging for bundled build.
8
9 When NULL is received for an optional argument we should not set an
10 error message as this would block later error messages. If NULL is
11 received for a non-optional string we should set has_error. Set
12 has_error for UTF-8 errors to ensure optional strings with UTF-8
13 errors are not replaced with json_null(). Use 'purpose' argument in
14 NULL error messages of read_string.
15
16 Add error handling and tests for invalid formats where '+', '#', or '%'
17 is used on an optional string 's?' or 's*'.
18
19 Fix NULL string error messages to use 'purpose'.
20
21 Refactor skipping of '*' token, this is now handled by read_string and
22 pack_object_inter. This allows invalid format strings such as 's*#' and
23 's*+' to produce error messages.
24
25 Fixes #437
26 ---
27  src/pack_unpack.c           | 74 +++++++++++++++++++++++--------------
28  test/suites/api/test_pack.c | 49 ++++++++++++++++++++++--
29  2 files changed, 93 insertions(+), 30 deletions(-)
30
31 diff --git a/src/pack_unpack.c b/src/pack_unpack.c
32 index b842772..fc98df4 100644
33 --- a/src/pack_unpack.c
34 +++ b/src/pack_unpack.c
35 @@ -130,7 +130,7 @@ static json_t *pack(scanner_t *s, va_list *ap);
36  /* ours will be set to 1 if jsonp_free() must be called for the result
37     afterwards */
38  static char *read_string(scanner_t *s, va_list *ap,
39 -                         const char *purpose, size_t *out_len, int *ours)
40 +                         const char *purpose, size_t *out_len, int *ours, int optional)
41  {
42      char t;
43      strbuffer_t strbuff;
44 @@ -147,7 +147,10 @@ static char *read_string(scanner_t *s, va_list *ap,
45          str = va_arg(*ap, const char *);
46  
47          if(!str) {
48 -            set_error(s, "<args>", json_error_null_value, "NULL string argument");
49 +            if (!optional) {
50 +                set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
51 +                s->has_error = 1;
52 +            }
53              return NULL;
54          }
55  
56 @@ -155,11 +158,17 @@ static char *read_string(scanner_t *s, va_list *ap,
57  
58          if(!utf8_check_string(str, length)) {
59              set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
60 +            s->has_error = 1;
61              return NULL;
62          }
63  
64          *out_len = length;
65          return (char *)str;
66 +    } else if (optional) {
67 +        set_error(s, "<format>", json_error_invalid_format, "Cannot use '%c' on optional strings", t);
68 +        s->has_error = 1;
69 +
70 +        return NULL;
71      }
72  
73      if(strbuffer_init(&strbuff)) {
74 @@ -170,7 +179,7 @@ static char *read_string(scanner_t *s, va_list *ap,
75      while(1) {
76          str = va_arg(*ap, const char *);
77          if(!str) {
78 -            set_error(s, "<args>", json_error_null_value, "NULL string argument");
79 +            set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
80              s->has_error = 1;
81          }
82  
83 @@ -226,6 +235,7 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
84          size_t len;
85          int ours;
86          json_t *value;
87 +        char valueOptional;
88  
89          if(!token(s)) {
90              set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
91 @@ -237,20 +247,21 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
92              goto error;
93          }
94  
95 -        key = read_string(s, ap, "object key", &len, &ours);
96 -        if (!key)
97 -            s->has_error = 1;
98 +        key = read_string(s, ap, "object key", &len, &ours, 0);
99  
100          next_token(s);
101  
102 +        next_token(s);
103 +        valueOptional = token(s);
104 +        prev_token(s);
105 +
106          value = pack(s, ap);
107          if(!value) {
108              if(ours)
109                  jsonp_free(key);
110  
111 -            if(strchr("soO", token(s)) && s->next_token.token == '*') {
112 -                next_token(s);
113 -            } else {
114 +            if(valueOptional != '*') {
115 +                set_error(s, "<args>", json_error_null_value, "NULL object value\n");
116                  s->has_error = 1;
117              }
118  
119 @@ -269,8 +280,6 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
120          if(ours)
121              jsonp_free(key);
122  
123 -        if(strchr("soO", token(s)) && s->next_token.token == '*')
124 -            next_token(s);
125          next_token(s);
126      }
127  
128 @@ -289,6 +298,7 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
129  
130      while(token(s) != ']') {
131          json_t *value;
132 +        char valueOptional;
133  
134          if(!token(s)) {
135              set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
136 @@ -296,11 +306,13 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
137              goto error;
138          }
139  
140 +        next_token(s);
141 +        valueOptional = token(s);
142 +        prev_token(s);
143 +
144          value = pack(s, ap);
145          if(!value) {
146 -            if(strchr("soO", token(s)) && s->next_token.token == '*') {
147 -                next_token(s);
148 -            } else {
149 +            if(valueOptional != '*') {
150                  s->has_error = 1;
151              }
152  
153 @@ -316,8 +328,6 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
154              s->has_error = 1;
155          }
156  
157 -        if(strchr("soO", token(s)) && s->next_token.token == '*')
158 -            next_token(s);
159          next_token(s);
160      }
161  
162 @@ -332,23 +342,33 @@ error:
163  static json_t *pack_string(scanner_t *s, va_list *ap)
164  {
165      char *str;
166 +    char t;
167      size_t len;
168      int ours;
169 -    int nullable;
170 +    int optional;
171  
172      next_token(s);
173 -    nullable = token(s) == '?';
174 -    if (!nullable)
175 +    t = token(s);
176 +    optional = t == '?' || t == '*';
177 +    if (!optional)
178          prev_token(s);
179  
180 -    str = read_string(s, ap, "string", &len, &ours);
181 -    if (!str) {
182 -        return nullable ? json_null() : NULL;
183 -    } else if (ours) {
184 -        return jsonp_stringn_nocheck_own(str, len);
185 -    } else {
186 -        return json_stringn_nocheck(str, len);
187 +    str = read_string(s, ap, "string", &len, &ours, optional);
188 +
189 +    if (!str)
190 +        return t == '?' && !s->has_error ? json_null() : NULL;
191 +
192 +    if (s->has_error) {
193 +        if (!ours)
194 +            jsonp_free(str);
195 +
196 +        return NULL;
197      }
198 +
199 +    if (ours)
200 +        return jsonp_stringn_nocheck_own(str, len);
201 +
202 +    return json_stringn_nocheck(str, len);
203  }
204  
205  static json_t *pack_object_inter(scanner_t *s, va_list *ap, int need_incref)
206 @@ -359,7 +379,7 @@ static json_t *pack_object_inter(scanner_t *s, va_list *ap, int need_incref)
207      next_token(s);
208      ntoken = token(s);
209  
210 -    if (ntoken != '?')
211 +    if (ntoken != '?' && ntoken != '*')
212          prev_token(s);
213  
214      json = va_arg(*ap, json_t *);
215 -- 
216 2.17.1
217