1*48c779cdSXin LI /*- 2*48c779cdSXin LI * Copyright (c) 2018 Christos Zoulas 3*48c779cdSXin LI * All rights reserved. 4*48c779cdSXin LI * 5*48c779cdSXin LI * Redistribution and use in source and binary forms, with or without 6*48c779cdSXin LI * modification, are permitted provided that the following conditions 7*48c779cdSXin LI * are met: 8*48c779cdSXin LI * 1. Redistributions of source code must retain the above copyright 9*48c779cdSXin LI * notice, this list of conditions and the following disclaimer. 10*48c779cdSXin LI * 2. Redistributions in binary form must reproduce the above copyright 11*48c779cdSXin LI * notice, this list of conditions and the following disclaimer in the 12*48c779cdSXin LI * documentation and/or other materials provided with the distribution. 13*48c779cdSXin LI * 14*48c779cdSXin LI * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15*48c779cdSXin LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16*48c779cdSXin LI * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17*48c779cdSXin LI * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18*48c779cdSXin LI * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19*48c779cdSXin LI * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20*48c779cdSXin LI * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21*48c779cdSXin LI * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22*48c779cdSXin LI * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23*48c779cdSXin LI * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24*48c779cdSXin LI * POSSIBILITY OF SUCH DAMAGE. 25*48c779cdSXin LI */ 26*48c779cdSXin LI 27*48c779cdSXin LI /* 28*48c779cdSXin LI * Parse JSON object serialization format (RFC-7159) 29*48c779cdSXin LI */ 30*48c779cdSXin LI 31*48c779cdSXin LI #ifndef TEST 32*48c779cdSXin LI #include "file.h" 33*48c779cdSXin LI 34*48c779cdSXin LI #ifndef lint 35*48c779cdSXin LI FILE_RCSID("@(#)$File: is_json.c,v 1.13 2019/03/02 01:08:10 christos Exp $") 36*48c779cdSXin LI #endif 37*48c779cdSXin LI 38*48c779cdSXin LI #include <string.h> 39*48c779cdSXin LI #include "magic.h" 40*48c779cdSXin LI #endif 41*48c779cdSXin LI 42*48c779cdSXin LI #ifdef DEBUG 43*48c779cdSXin LI #include <stdio.h> 44*48c779cdSXin LI #define DPRINTF(a, b, c) \ 45*48c779cdSXin LI printf("%s [%.2x/%c] %.20s\n", (a), *(b), *(b), (const char *)(c)) 46*48c779cdSXin LI #else 47*48c779cdSXin LI #define DPRINTF(a, b, c) do { } while (/*CONSTCOND*/0) 48*48c779cdSXin LI #endif 49*48c779cdSXin LI 50*48c779cdSXin LI #define JSON_ARRAY 0 51*48c779cdSXin LI #define JSON_CONSTANT 1 52*48c779cdSXin LI #define JSON_NUMBER 2 53*48c779cdSXin LI #define JSON_OBJECT 3 54*48c779cdSXin LI #define JSON_STRING 4 55*48c779cdSXin LI #define JSON_ARRAYN 5 56*48c779cdSXin LI #define JSON_MAX 6 57*48c779cdSXin LI 58*48c779cdSXin LI /* 59*48c779cdSXin LI * if JSON_COUNT != 0: 60*48c779cdSXin LI * count all the objects, require that we have the whole data file 61*48c779cdSXin LI * otherwise: 62*48c779cdSXin LI * stop if we find an object or an array 63*48c779cdSXin LI */ 64*48c779cdSXin LI #ifndef JSON_COUNT 65*48c779cdSXin LI #define JSON_COUNT 0 66*48c779cdSXin LI #endif 67*48c779cdSXin LI 68*48c779cdSXin LI static int json_parse(const unsigned char **, const unsigned char *, size_t *, 69*48c779cdSXin LI size_t); 70*48c779cdSXin LI 71*48c779cdSXin LI static int 72*48c779cdSXin LI json_isspace(const unsigned char uc) 73*48c779cdSXin LI { 74*48c779cdSXin LI switch (uc) { 75*48c779cdSXin LI case ' ': 76*48c779cdSXin LI case '\n': 77*48c779cdSXin LI case '\r': 78*48c779cdSXin LI case '\t': 79*48c779cdSXin LI return 1; 80*48c779cdSXin LI default: 81*48c779cdSXin LI return 0; 82*48c779cdSXin LI } 83*48c779cdSXin LI } 84*48c779cdSXin LI 85*48c779cdSXin LI static int 86*48c779cdSXin LI json_isdigit(unsigned char uc) 87*48c779cdSXin LI { 88*48c779cdSXin LI switch (uc) { 89*48c779cdSXin LI case '0': case '1': case '2': case '3': case '4': 90*48c779cdSXin LI case '5': case '6': case '7': case '8': case '9': 91*48c779cdSXin LI return 1; 92*48c779cdSXin LI default: 93*48c779cdSXin LI return 0; 94*48c779cdSXin LI } 95*48c779cdSXin LI } 96*48c779cdSXin LI 97*48c779cdSXin LI static int 98*48c779cdSXin LI json_isxdigit(unsigned char uc) 99*48c779cdSXin LI { 100*48c779cdSXin LI if (json_isdigit(uc)) 101*48c779cdSXin LI return 1; 102*48c779cdSXin LI switch (uc) { 103*48c779cdSXin LI case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 104*48c779cdSXin LI case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 105*48c779cdSXin LI return 1; 106*48c779cdSXin LI default: 107*48c779cdSXin LI return 0; 108*48c779cdSXin LI } 109*48c779cdSXin LI } 110*48c779cdSXin LI 111*48c779cdSXin LI static const unsigned char * 112*48c779cdSXin LI json_skip_space(const unsigned char *uc, const unsigned char *ue) 113*48c779cdSXin LI { 114*48c779cdSXin LI while (uc < ue && json_isspace(*uc)) 115*48c779cdSXin LI uc++; 116*48c779cdSXin LI return uc; 117*48c779cdSXin LI } 118*48c779cdSXin LI 119*48c779cdSXin LI static int 120*48c779cdSXin LI json_parse_string(const unsigned char **ucp, const unsigned char *ue) 121*48c779cdSXin LI { 122*48c779cdSXin LI const unsigned char *uc = *ucp; 123*48c779cdSXin LI size_t i; 124*48c779cdSXin LI 125*48c779cdSXin LI DPRINTF("Parse string: ", uc, *ucp); 126*48c779cdSXin LI while (uc < ue) { 127*48c779cdSXin LI switch (*uc++) { 128*48c779cdSXin LI case '\0': 129*48c779cdSXin LI goto out; 130*48c779cdSXin LI case '\\': 131*48c779cdSXin LI if (uc == ue) 132*48c779cdSXin LI goto out; 133*48c779cdSXin LI switch (*uc++) { 134*48c779cdSXin LI case '\0': 135*48c779cdSXin LI goto out; 136*48c779cdSXin LI case '"': 137*48c779cdSXin LI case '\\': 138*48c779cdSXin LI case '/': 139*48c779cdSXin LI case 'b': 140*48c779cdSXin LI case 'f': 141*48c779cdSXin LI case 'n': 142*48c779cdSXin LI case 'r': 143*48c779cdSXin LI case 't': 144*48c779cdSXin LI continue; 145*48c779cdSXin LI case 'u': 146*48c779cdSXin LI if (ue - uc < 4) { 147*48c779cdSXin LI uc = ue; 148*48c779cdSXin LI goto out; 149*48c779cdSXin LI } 150*48c779cdSXin LI for (i = 0; i < 4; i++) 151*48c779cdSXin LI if (!json_isxdigit(*uc++)) 152*48c779cdSXin LI goto out; 153*48c779cdSXin LI continue; 154*48c779cdSXin LI default: 155*48c779cdSXin LI goto out; 156*48c779cdSXin LI } 157*48c779cdSXin LI case '"': 158*48c779cdSXin LI *ucp = uc; 159*48c779cdSXin LI return 1; 160*48c779cdSXin LI default: 161*48c779cdSXin LI continue; 162*48c779cdSXin LI } 163*48c779cdSXin LI } 164*48c779cdSXin LI out: 165*48c779cdSXin LI DPRINTF("Bad string: ", uc, *ucp); 166*48c779cdSXin LI *ucp = uc; 167*48c779cdSXin LI return 0; 168*48c779cdSXin LI } 169*48c779cdSXin LI 170*48c779cdSXin LI static int 171*48c779cdSXin LI json_parse_array(const unsigned char **ucp, const unsigned char *ue, 172*48c779cdSXin LI size_t *st, size_t lvl) 173*48c779cdSXin LI { 174*48c779cdSXin LI const unsigned char *uc = *ucp; 175*48c779cdSXin LI int more = 0; /* Array has more than 1 element */ 176*48c779cdSXin LI 177*48c779cdSXin LI DPRINTF("Parse array: ", uc, *ucp); 178*48c779cdSXin LI while (uc < ue) { 179*48c779cdSXin LI if (!json_parse(&uc, ue, st, lvl + 1)) 180*48c779cdSXin LI goto out; 181*48c779cdSXin LI if (uc == ue) 182*48c779cdSXin LI goto out; 183*48c779cdSXin LI switch (*uc) { 184*48c779cdSXin LI case ',': 185*48c779cdSXin LI more++; 186*48c779cdSXin LI uc++; 187*48c779cdSXin LI continue; 188*48c779cdSXin LI case ']': 189*48c779cdSXin LI if (more) 190*48c779cdSXin LI st[JSON_ARRAYN]++; 191*48c779cdSXin LI *ucp = uc + 1; 192*48c779cdSXin LI return 1; 193*48c779cdSXin LI default: 194*48c779cdSXin LI goto out; 195*48c779cdSXin LI } 196*48c779cdSXin LI } 197*48c779cdSXin LI out: 198*48c779cdSXin LI DPRINTF("Bad array: ", uc, *ucp); 199*48c779cdSXin LI *ucp = uc; 200*48c779cdSXin LI return 0; 201*48c779cdSXin LI } 202*48c779cdSXin LI 203*48c779cdSXin LI static int 204*48c779cdSXin LI json_parse_object(const unsigned char **ucp, const unsigned char *ue, 205*48c779cdSXin LI size_t *st, size_t lvl) 206*48c779cdSXin LI { 207*48c779cdSXin LI const unsigned char *uc = *ucp; 208*48c779cdSXin LI DPRINTF("Parse object: ", uc, *ucp); 209*48c779cdSXin LI while (uc < ue) { 210*48c779cdSXin LI uc = json_skip_space(uc, ue); 211*48c779cdSXin LI if (uc == ue) 212*48c779cdSXin LI goto out; 213*48c779cdSXin LI if (*uc++ != '"') { 214*48c779cdSXin LI DPRINTF("not string", uc, *ucp); 215*48c779cdSXin LI goto out; 216*48c779cdSXin LI } 217*48c779cdSXin LI DPRINTF("next field", uc, *ucp); 218*48c779cdSXin LI if (!json_parse_string(&uc, ue)) { 219*48c779cdSXin LI DPRINTF("not string", uc, *ucp); 220*48c779cdSXin LI goto out; 221*48c779cdSXin LI } 222*48c779cdSXin LI uc = json_skip_space(uc, ue); 223*48c779cdSXin LI if (uc == ue) 224*48c779cdSXin LI goto out; 225*48c779cdSXin LI if (*uc++ != ':') { 226*48c779cdSXin LI DPRINTF("not colon", uc, *ucp); 227*48c779cdSXin LI goto out; 228*48c779cdSXin LI } 229*48c779cdSXin LI if (!json_parse(&uc, ue, st, lvl + 1)) { 230*48c779cdSXin LI DPRINTF("not json", uc, *ucp); 231*48c779cdSXin LI goto out; 232*48c779cdSXin LI } 233*48c779cdSXin LI if (uc == ue) 234*48c779cdSXin LI goto out; 235*48c779cdSXin LI switch (*uc++) { 236*48c779cdSXin LI case ',': 237*48c779cdSXin LI continue; 238*48c779cdSXin LI case '}': /* { */ 239*48c779cdSXin LI *ucp = uc; 240*48c779cdSXin LI DPRINTF("Good object: ", uc, *ucp); 241*48c779cdSXin LI return 1; 242*48c779cdSXin LI default: 243*48c779cdSXin LI *ucp = uc - 1; 244*48c779cdSXin LI DPRINTF("not more", uc, *ucp); 245*48c779cdSXin LI goto out; 246*48c779cdSXin LI } 247*48c779cdSXin LI } 248*48c779cdSXin LI out: 249*48c779cdSXin LI DPRINTF("Bad object: ", uc, *ucp); 250*48c779cdSXin LI *ucp = uc; 251*48c779cdSXin LI return 0; 252*48c779cdSXin LI } 253*48c779cdSXin LI 254*48c779cdSXin LI static int 255*48c779cdSXin LI json_parse_number(const unsigned char **ucp, const unsigned char *ue) 256*48c779cdSXin LI { 257*48c779cdSXin LI const unsigned char *uc = *ucp; 258*48c779cdSXin LI int got = 0; 259*48c779cdSXin LI 260*48c779cdSXin LI DPRINTF("Parse number: ", uc, *ucp); 261*48c779cdSXin LI if (uc == ue) 262*48c779cdSXin LI return 0; 263*48c779cdSXin LI if (*uc == '-') 264*48c779cdSXin LI uc++; 265*48c779cdSXin LI 266*48c779cdSXin LI for (; uc < ue; uc++) { 267*48c779cdSXin LI if (!json_isdigit(*uc)) 268*48c779cdSXin LI break; 269*48c779cdSXin LI got = 1; 270*48c779cdSXin LI } 271*48c779cdSXin LI if (uc == ue) 272*48c779cdSXin LI goto out; 273*48c779cdSXin LI if (*uc == '.') 274*48c779cdSXin LI uc++; 275*48c779cdSXin LI for (; uc < ue; uc++) { 276*48c779cdSXin LI if (!json_isdigit(*uc)) 277*48c779cdSXin LI break; 278*48c779cdSXin LI got = 1; 279*48c779cdSXin LI } 280*48c779cdSXin LI if (uc == ue) 281*48c779cdSXin LI goto out; 282*48c779cdSXin LI if (got && (*uc == 'e' || *uc == 'E')) { 283*48c779cdSXin LI uc++; 284*48c779cdSXin LI got = 0; 285*48c779cdSXin LI if (uc == ue) 286*48c779cdSXin LI goto out; 287*48c779cdSXin LI if (*uc == '+' || *uc == '-') 288*48c779cdSXin LI uc++; 289*48c779cdSXin LI for (; uc < ue; uc++) { 290*48c779cdSXin LI if (!json_isdigit(*uc)) 291*48c779cdSXin LI break; 292*48c779cdSXin LI got = 1; 293*48c779cdSXin LI } 294*48c779cdSXin LI } 295*48c779cdSXin LI out: 296*48c779cdSXin LI if (!got) 297*48c779cdSXin LI DPRINTF("Bad number: ", uc, *ucp); 298*48c779cdSXin LI else 299*48c779cdSXin LI DPRINTF("Good number: ", uc, *ucp); 300*48c779cdSXin LI *ucp = uc; 301*48c779cdSXin LI return got; 302*48c779cdSXin LI } 303*48c779cdSXin LI 304*48c779cdSXin LI static int 305*48c779cdSXin LI json_parse_const(const unsigned char **ucp, const unsigned char *ue, 306*48c779cdSXin LI const char *str, size_t len) 307*48c779cdSXin LI { 308*48c779cdSXin LI const unsigned char *uc = *ucp; 309*48c779cdSXin LI 310*48c779cdSXin LI DPRINTF("Parse const: ", uc, *ucp); 311*48c779cdSXin LI for (len--; uc < ue && --len;) { 312*48c779cdSXin LI if (*uc++ == *++str) 313*48c779cdSXin LI continue; 314*48c779cdSXin LI } 315*48c779cdSXin LI if (len) 316*48c779cdSXin LI DPRINTF("Bad const: ", uc, *ucp); 317*48c779cdSXin LI *ucp = uc; 318*48c779cdSXin LI return len == 0; 319*48c779cdSXin LI } 320*48c779cdSXin LI 321*48c779cdSXin LI static int 322*48c779cdSXin LI json_parse(const unsigned char **ucp, const unsigned char *ue, 323*48c779cdSXin LI size_t *st, size_t lvl) 324*48c779cdSXin LI { 325*48c779cdSXin LI const unsigned char *uc; 326*48c779cdSXin LI int rv = 0; 327*48c779cdSXin LI int t; 328*48c779cdSXin LI 329*48c779cdSXin LI uc = json_skip_space(*ucp, ue); 330*48c779cdSXin LI if (uc == ue) 331*48c779cdSXin LI goto out; 332*48c779cdSXin LI 333*48c779cdSXin LI // Avoid recursion 334*48c779cdSXin LI if (lvl > 20) 335*48c779cdSXin LI return 0; 336*48c779cdSXin LI #if JSON_COUNT 337*48c779cdSXin LI /* bail quickly if not counting */ 338*48c779cdSXin LI if (lvl > 1 && (st[JSON_OBJECT] || st[JSON_ARRAYN])) 339*48c779cdSXin LI return 1; 340*48c779cdSXin LI #endif 341*48c779cdSXin LI 342*48c779cdSXin LI DPRINTF("Parse general: ", uc, *ucp); 343*48c779cdSXin LI switch (*uc++) { 344*48c779cdSXin LI case '"': 345*48c779cdSXin LI rv = json_parse_string(&uc, ue); 346*48c779cdSXin LI t = JSON_STRING; 347*48c779cdSXin LI break; 348*48c779cdSXin LI case '[': 349*48c779cdSXin LI rv = json_parse_array(&uc, ue, st, lvl + 1); 350*48c779cdSXin LI t = JSON_ARRAY; 351*48c779cdSXin LI break; 352*48c779cdSXin LI case '{': /* '}' */ 353*48c779cdSXin LI rv = json_parse_object(&uc, ue, st, lvl + 1); 354*48c779cdSXin LI t = JSON_OBJECT; 355*48c779cdSXin LI break; 356*48c779cdSXin LI case 't': 357*48c779cdSXin LI rv = json_parse_const(&uc, ue, "true", sizeof("true")); 358*48c779cdSXin LI t = JSON_CONSTANT; 359*48c779cdSXin LI break; 360*48c779cdSXin LI case 'f': 361*48c779cdSXin LI rv = json_parse_const(&uc, ue, "false", sizeof("false")); 362*48c779cdSXin LI t = JSON_CONSTANT; 363*48c779cdSXin LI break; 364*48c779cdSXin LI case 'n': 365*48c779cdSXin LI rv = json_parse_const(&uc, ue, "null", sizeof("null")); 366*48c779cdSXin LI t = JSON_CONSTANT; 367*48c779cdSXin LI break; 368*48c779cdSXin LI default: 369*48c779cdSXin LI --uc; 370*48c779cdSXin LI rv = json_parse_number(&uc, ue); 371*48c779cdSXin LI t = JSON_NUMBER; 372*48c779cdSXin LI break; 373*48c779cdSXin LI } 374*48c779cdSXin LI if (rv) 375*48c779cdSXin LI st[t]++; 376*48c779cdSXin LI uc = json_skip_space(uc, ue); 377*48c779cdSXin LI out: 378*48c779cdSXin LI *ucp = uc; 379*48c779cdSXin LI DPRINTF("End general: ", uc, *ucp); 380*48c779cdSXin LI if (lvl == 0) 381*48c779cdSXin LI return rv && (st[JSON_ARRAYN] || st[JSON_OBJECT]); 382*48c779cdSXin LI return rv; 383*48c779cdSXin LI } 384*48c779cdSXin LI 385*48c779cdSXin LI #ifndef TEST 386*48c779cdSXin LI int 387*48c779cdSXin LI file_is_json(struct magic_set *ms, const struct buffer *b) 388*48c779cdSXin LI { 389*48c779cdSXin LI const unsigned char *uc = CAST(const unsigned char *, b->fbuf); 390*48c779cdSXin LI const unsigned char *ue = uc + b->flen; 391*48c779cdSXin LI size_t st[JSON_MAX]; 392*48c779cdSXin LI int mime = ms->flags & MAGIC_MIME; 393*48c779cdSXin LI 394*48c779cdSXin LI 395*48c779cdSXin LI if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) 396*48c779cdSXin LI return 0; 397*48c779cdSXin LI 398*48c779cdSXin LI memset(st, 0, sizeof(st)); 399*48c779cdSXin LI 400*48c779cdSXin LI if (!json_parse(&uc, ue, st, 0)) 401*48c779cdSXin LI return 0; 402*48c779cdSXin LI 403*48c779cdSXin LI if (mime == MAGIC_MIME_ENCODING) 404*48c779cdSXin LI return 1; 405*48c779cdSXin LI if (mime) { 406*48c779cdSXin LI if (file_printf(ms, "application/json") == -1) 407*48c779cdSXin LI return -1; 408*48c779cdSXin LI return 1; 409*48c779cdSXin LI } 410*48c779cdSXin LI if (file_printf(ms, "JSON data") == -1) 411*48c779cdSXin LI return -1; 412*48c779cdSXin LI #if JSON_COUNT 413*48c779cdSXin LI #define P(n) st[n], st[n] > 1 ? "s" : "" 414*48c779cdSXin LI if (file_printf(ms, " (%" SIZE_T_FORMAT "u object%s, %" SIZE_T_FORMAT 415*48c779cdSXin LI "u array%s, %" SIZE_T_FORMAT "u string%s, %" SIZE_T_FORMAT 416*48c779cdSXin LI "u constant%s, %" SIZE_T_FORMAT "u number%s, %" SIZE_T_FORMAT 417*48c779cdSXin LI "u >1array%s)", 418*48c779cdSXin LI P(JSON_OBJECT), P(JSON_ARRAY), P(JSON_STRING), P(JSON_CONSTANT), 419*48c779cdSXin LI P(JSON_NUMBER), P(JSON_ARRAYN)) 420*48c779cdSXin LI == -1) 421*48c779cdSXin LI return -1; 422*48c779cdSXin LI #endif 423*48c779cdSXin LI return 1; 424*48c779cdSXin LI } 425*48c779cdSXin LI 426*48c779cdSXin LI #else 427*48c779cdSXin LI 428*48c779cdSXin LI #include <sys/types.h> 429*48c779cdSXin LI #include <sys/stat.h> 430*48c779cdSXin LI #include <stdio.h> 431*48c779cdSXin LI #include <fcntl.h> 432*48c779cdSXin LI #include <unistd.h> 433*48c779cdSXin LI #include <stdlib.h> 434*48c779cdSXin LI #include <stdint.h> 435*48c779cdSXin LI #include <err.h> 436*48c779cdSXin LI 437*48c779cdSXin LI int 438*48c779cdSXin LI main(int argc, char *argv[]) 439*48c779cdSXin LI { 440*48c779cdSXin LI int fd, rv; 441*48c779cdSXin LI struct stat st; 442*48c779cdSXin LI unsigned char *p; 443*48c779cdSXin LI size_t stats[JSON_MAX]; 444*48c779cdSXin LI 445*48c779cdSXin LI if ((fd = open(argv[1], O_RDONLY)) == -1) 446*48c779cdSXin LI err(EXIT_FAILURE, "Can't open `%s'", argv[1]); 447*48c779cdSXin LI 448*48c779cdSXin LI if (fstat(fd, &st) == -1) 449*48c779cdSXin LI err(EXIT_FAILURE, "Can't stat `%s'", argv[1]); 450*48c779cdSXin LI 451*48c779cdSXin LI if ((p = malloc(st.st_size)) == NULL) 452*48c779cdSXin LI err(EXIT_FAILURE, "Can't allocate %jd bytes", 453*48c779cdSXin LI (intmax_t)st.st_size); 454*48c779cdSXin LI if (read(fd, p, st.st_size) != st.st_size) 455*48c779cdSXin LI err(EXIT_FAILURE, "Can't read %jd bytes", 456*48c779cdSXin LI (intmax_t)st.st_size); 457*48c779cdSXin LI memset(stats, 0, sizeof(stats)); 458*48c779cdSXin LI printf("is json %d\n", json_parse((const unsigned char **)&p, 459*48c779cdSXin LI p + st.st_size, stats, 0)); 460*48c779cdSXin LI return 0; 461*48c779cdSXin LI } 462*48c779cdSXin LI #endif 463