11/* MIT (BSD) license - see LICENSE file for details */
22#include <ccan/json_escape/json_escape.h>
33#include <stdio.h>
4+ #include <ccan/tal/str/str.h>
45
56struct json_escape * json_escape_string_ (const tal_t * ctx ,
67 const void * bytes , size_t len )
@@ -137,19 +138,24 @@ struct json_escape *json_escape_len(const tal_t *ctx, const char *str TAKES,
137138}
138139
139140/* By policy, we don't handle \u. Use UTF-8. */
140- const char * json_escape_unescape (const tal_t * ctx , const struct json_escape * esc )
141+ static const char * unescape (const tal_t * ctx , const char * esc TAKES , size_t len )
141142{
142- char * unesc = tal_arr (ctx , char , strlen (esc -> s ) + 1 );
143+ /* Fast path: can steal, and nothing to unescape. */
144+ if (is_taken (esc ) && !memchr (esc , '\\' , len ))
145+ return tal_strndup (ctx , esc , len );
146+
147+ char * unesc = tal_arr (ctx , char , len + 1 );
143148 size_t i , n ;
144149
145- for (i = n = 0 ; esc -> s [ i ] ; i ++ , n ++ ) {
146- if (esc -> s [i ] != '\\' ) {
147- unesc [n ] = esc -> s [i ];
150+ for (i = n = 0 ; i < len ; i ++ , n ++ ) {
151+ if (esc [i ] != '\\' ) {
152+ unesc [n ] = esc [i ];
148153 continue ;
149154 }
150155
151- i ++ ;
152- switch (esc -> s [i ]) {
156+ if (++ i == len )
157+ goto error ;
158+ switch (esc [i ]) {
153159 case 'n' :
154160 unesc [n ] = '\n' ;
155161 break ;
@@ -168,13 +174,31 @@ const char *json_escape_unescape(const tal_t *ctx, const struct json_escape *esc
168174 case '/' :
169175 case '\\' :
170176 case '"' :
171- unesc [n ] = esc -> s [i ];
177+ unesc [n ] = esc [i ];
172178 break ;
173179 default :
180+ error :
181+ if (taken (esc ))
182+ tal_free (esc );
174183 return tal_free (unesc );
175184 }
176185 }
177186
178187 unesc [n ] = '\0' ;
188+ if (!tal_resize (& unesc , n + 1 ))
189+ goto error ;
190+ if (taken (esc ))
191+ tal_free (esc );
179192 return unesc ;
180193}
194+
195+ const char * json_escape_unescape (const tal_t * ctx , const struct json_escape * esc )
196+ {
197+ return unescape (ctx , esc -> s , strlen (esc -> s ));
198+ }
199+
200+ const char * json_escape_unescape_len (const tal_t * ctx ,
201+ const char * esc TAKES , size_t len )
202+ {
203+ return unescape (ctx , esc , len );
204+ }
0 commit comments