Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/winpr/libwinpr/utils/json/json.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * JSON parser wrapper
4
 *
5
 * Copyright 2024 Armin Novak <anovak@thincast.com>
6
 * Copyright 2024 Thincast Technologies GmbH
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
#include <math.h>
21
#include <errno.h>
22
23
#include <winpr/file.h>
24
#include <winpr/json.h>
25
#include <winpr/assert.h>
26
27
#if defined(WITH_CJSON)
28
#include <cjson/cJSON.h>
29
#endif
30
#if defined(WITH_JSONC)
31
#include <json.h>
32
#endif
33
34
#if defined(WITH_CJSON)
35
#if CJSON_VERSION_MAJOR == 1
36
#if (CJSON_VERSION_MINOR < 7) || ((CJSON_VERSION_MINOR == 7) && (CJSON_VERSION_PATCH < 13))
37
#define USE_CJSON_COMPAT
38
#endif
39
#endif
40
#endif
41
42
#if defined(WITH_JSONC)
43
#if JSON_C_MAJOR_VERSION == 0
44
#if JSON_C_MINOR_VERSION < 14
45
static struct json_object* json_object_new_null(void)
46
0
{
47
0
  return NULL;
48
0
}
49
#endif
50
#endif
51
#endif
52
53
#if defined(USE_CJSON_COMPAT)
54
static double cJSON_GetNumberValue(const cJSON* prop)
55
{
56
#ifndef NAN
57
#ifdef _WIN32
58
#define NAN sqrt(-1.0)
59
#define COMPAT_NAN_UNDEF
60
#else
61
#define NAN 0.0 / 0.0
62
#define COMPAT_NAN_UNDEF
63
#endif
64
#endif
65
66
  if (!cJSON_IsNumber(prop))
67
    return NAN;
68
  char* val = cJSON_GetStringValue(prop);
69
  if (!val)
70
    return NAN;
71
72
  errno = 0;
73
  char* endptr = NULL;
74
  double dval = strtod(val, &endptr);
75
  if (val == endptr)
76
    return NAN;
77
  if (endptr != NULL)
78
    return NAN;
79
  if (errno != 0)
80
    return NAN;
81
  return dval;
82
83
#ifdef COMPAT_NAN_UNDEF
84
#undef NAN
85
#endif
86
}
87
88
static cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length)
89
{
90
  // Check for string '\0' termination.
91
  const size_t slen = strnlen(value, buffer_length);
92
  if (slen >= buffer_length)
93
  {
94
    if (value[buffer_length] != '\0')
95
      return NULL;
96
  }
97
  return cJSON_Parse(value);
98
}
99
#endif
100
101
int WINPR_JSON_version(char* buffer, size_t len)
102
0
{
103
0
#if defined(WITH_JSONC)
104
0
  return _snprintf(buffer, len, "json-c %s", json_c_version());
105
#elif defined(WITH_CJSON)
106
  return _snprintf(buffer, len, "cJSON %s", cJSON_Version());
107
#else
108
  (void)_snprintf(buffer, len, "JSON support not available");
109
  return -1;
110
#endif
111
0
}
112
113
WINPR_JSON* WINPR_JSON_Parse(const char* value)
114
0
{
115
0
#if defined(WITH_JSONC)
116
0
  return json_tokener_parse(value);
117
#elif defined(WITH_CJSON)
118
  return cJSON_Parse(value);
119
#else
120
  WINPR_UNUSED(value);
121
  return NULL;
122
#endif
123
0
}
124
125
WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length)
126
0
{
127
0
#if defined(WITH_JSONC)
128
0
  WINPR_ASSERT(buffer_length <= INT_MAX);
129
0
  json_tokener* tok = json_tokener_new();
130
0
  if (!tok)
131
0
    return NULL;
132
0
  json_object* obj = json_tokener_parse_ex(tok, value, (int)buffer_length);
133
0
  json_tokener_free(tok);
134
0
  return obj;
135
#elif defined(WITH_CJSON)
136
  return cJSON_ParseWithLength(value, buffer_length);
137
#else
138
  WINPR_UNUSED(value);
139
  WINPR_UNUSED(buffer_length);
140
  return NULL;
141
#endif
142
0
}
143
144
void WINPR_JSON_Delete(WINPR_JSON* item)
145
0
{
146
0
#if defined(WITH_JSONC)
147
0
  json_object_put((json_object*)item);
148
#elif defined(WITH_CJSON)
149
  cJSON_Delete((cJSON*)item);
150
#else
151
  WINPR_UNUSED(item);
152
#endif
153
0
}
154
155
WINPR_JSON* WINPR_JSON_GetArrayItem(const WINPR_JSON* array, size_t index)
156
0
{
157
0
#if defined(WITH_JSONC)
158
0
  return json_object_array_get_idx((const json_object*)array, index);
159
#elif defined(WITH_CJSON)
160
  WINPR_ASSERT(index <= INT_MAX);
161
  return cJSON_GetArrayItem((const cJSON*)array, (INT)index);
162
#else
163
  WINPR_UNUSED(array);
164
  WINPR_UNUSED(index);
165
  return NULL;
166
#endif
167
0
}
168
169
size_t WINPR_JSON_GetArraySize(const WINPR_JSON* array)
170
0
{
171
0
#if defined(WITH_JSONC)
172
0
  return json_object_array_length((const json_object*)array);
173
#elif defined(WITH_CJSON)
174
  const int rc = cJSON_GetArraySize((const cJSON*)array);
175
  if (rc <= 0)
176
    return 0;
177
  return (size_t)rc;
178
#else
179
  WINPR_UNUSED(array);
180
  return 0;
181
#endif
182
0
}
183
184
WINPR_JSON* WINPR_JSON_GetObjectItem(const WINPR_JSON* object, const char* string)
185
0
{
186
0
#if defined(WITH_JSONC)
187
0
  return json_object_object_get((const json_object*)object, string);
188
#elif defined(WITH_CJSON)
189
  return cJSON_GetObjectItem((const cJSON*)object, string);
190
#else
191
  WINPR_UNUSED(object);
192
  WINPR_UNUSED(string);
193
  return NULL;
194
#endif
195
0
}
196
197
WINPR_JSON* WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON* object, const char* string)
198
0
{
199
0
#if defined(WITH_JSONC)
200
0
  return json_object_object_get((const json_object*)object, string);
201
#elif defined(WITH_CJSON)
202
  return cJSON_GetObjectItemCaseSensitive((const cJSON*)object, string);
203
#else
204
  WINPR_UNUSED(object);
205
  WINPR_UNUSED(string);
206
  return NULL;
207
#endif
208
0
}
209
210
BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON* object, const char* string)
211
0
{
212
0
#if defined(WITH_JSONC)
213
0
  return json_object_object_get_ex((const json_object*)object, string, NULL);
214
#elif defined(WITH_CJSON)
215
  return cJSON_HasObjectItem((const cJSON*)object, string);
216
#else
217
  WINPR_UNUSED(object);
218
  WINPR_UNUSED(string);
219
  return FALSE;
220
#endif
221
0
}
222
223
const char* WINPR_JSON_GetErrorPtr(void)
224
0
{
225
0
#if defined(WITH_JSONC)
226
0
  return json_util_get_last_err();
227
#elif defined(WITH_CJSON)
228
  return cJSON_GetErrorPtr();
229
#else
230
  return NULL;
231
#endif
232
0
}
233
234
const char* WINPR_JSON_GetStringValue(WINPR_JSON* item)
235
0
{
236
0
#if defined(WITH_JSONC)
237
0
  return json_object_get_string((json_object*)item);
238
#elif defined(WITH_CJSON)
239
  return cJSON_GetStringValue((cJSON*)item);
240
#else
241
  WINPR_UNUSED(item);
242
  return NULL;
243
#endif
244
0
}
245
246
double WINPR_JSON_GetNumberValue(const WINPR_JSON* item)
247
0
{
248
0
#if defined(WITH_JSONC)
249
0
  return json_object_get_double((const json_object*)item);
250
#elif defined(WITH_CJSON)
251
  return cJSON_GetNumberValue((const cJSON*)item);
252
#else
253
  WINPR_UNUSED(item);
254
  return nan("");
255
#endif
256
0
}
257
258
BOOL WINPR_JSON_IsInvalid(const WINPR_JSON* item)
259
0
{
260
0
#if defined(WITH_JSONC)
261
0
  if (WINPR_JSON_IsArray(item))
262
0
    return FALSE;
263
0
  if (WINPR_JSON_IsObject(item))
264
0
    return FALSE;
265
0
  if (WINPR_JSON_IsNull(item))
266
0
    return FALSE;
267
0
  if (WINPR_JSON_IsNumber(item))
268
0
    return FALSE;
269
0
  if (WINPR_JSON_IsBool(item))
270
0
    return FALSE;
271
0
  if (WINPR_JSON_IsString(item))
272
0
    return FALSE;
273
0
  return TRUE;
274
#elif defined(WITH_CJSON)
275
  return cJSON_IsInvalid((const cJSON*)item);
276
#else
277
  WINPR_UNUSED(item);
278
  return TRUE;
279
#endif
280
0
}
281
282
BOOL WINPR_JSON_IsFalse(const WINPR_JSON* item)
283
0
{
284
0
#if defined(WITH_JSONC)
285
0
  if (!json_object_is_type((const json_object*)item, json_type_boolean))
286
0
    return FALSE;
287
0
  json_bool val = json_object_get_boolean((const json_object*)item);
288
0
  return val == 0;
289
#elif defined(WITH_CJSON)
290
  return cJSON_IsFalse((const cJSON*)item);
291
#else
292
  WINPR_UNUSED(item);
293
  return FALSE;
294
#endif
295
0
}
296
297
BOOL WINPR_JSON_IsTrue(const WINPR_JSON* item)
298
0
{
299
0
#if defined(WITH_JSONC)
300
0
  if (!json_object_is_type((const json_object*)item, json_type_boolean))
301
0
    return FALSE;
302
0
  json_bool val = json_object_get_boolean((const json_object*)item);
303
0
  return val != 0;
304
#elif defined(WITH_CJSON)
305
  return cJSON_IsTrue((const cJSON*)item);
306
#else
307
  WINPR_UNUSED(item);
308
  return FALSE;
309
#endif
310
0
}
311
312
BOOL WINPR_JSON_IsBool(const WINPR_JSON* item)
313
0
{
314
0
#if defined(WITH_JSONC)
315
0
  return json_object_is_type((const json_object*)item, json_type_boolean);
316
#elif defined(WITH_CJSON)
317
  return cJSON_IsBool((const cJSON*)item);
318
#else
319
  WINPR_UNUSED(item);
320
  return FALSE;
321
#endif
322
0
}
323
324
BOOL WINPR_JSON_IsNull(const WINPR_JSON* item)
325
0
{
326
0
#if defined(WITH_JSONC)
327
0
  return json_object_is_type((const json_object*)item, json_type_null);
328
#elif defined(WITH_CJSON)
329
  return cJSON_IsNull((const cJSON*)item);
330
#else
331
  WINPR_UNUSED(item);
332
  return FALSE;
333
#endif
334
0
}
335
336
BOOL WINPR_JSON_IsNumber(const WINPR_JSON* item)
337
0
{
338
0
#if defined(WITH_JSONC)
339
0
  return json_object_is_type((const json_object*)item, json_type_int) ||
340
0
         json_object_is_type((const json_object*)item, json_type_double);
341
#elif defined(WITH_CJSON)
342
  return cJSON_IsNumber((const cJSON*)item);
343
#else
344
  WINPR_UNUSED(item);
345
  return FALSE;
346
#endif
347
0
}
348
349
BOOL WINPR_JSON_IsString(const WINPR_JSON* item)
350
0
{
351
0
#if defined(WITH_JSONC)
352
0
  return json_object_is_type((const json_object*)item, json_type_string);
353
#elif defined(WITH_CJSON)
354
  return cJSON_IsString((const cJSON*)item);
355
#else
356
  WINPR_UNUSED(item);
357
  return FALSE;
358
#endif
359
0
}
360
361
BOOL WINPR_JSON_IsArray(const WINPR_JSON* item)
362
0
{
363
0
#if defined(WITH_JSONC)
364
0
  return json_object_is_type((const json_object*)item, json_type_array);
365
#elif defined(WITH_CJSON)
366
  return cJSON_IsArray((const cJSON*)item);
367
#else
368
  WINPR_UNUSED(item);
369
  return FALSE;
370
#endif
371
0
}
372
373
BOOL WINPR_JSON_IsObject(const WINPR_JSON* item)
374
0
{
375
0
#if defined(WITH_JSONC)
376
0
  return json_object_is_type((const json_object*)item, json_type_object);
377
#elif defined(WITH_CJSON)
378
  return cJSON_IsObject((const cJSON*)item);
379
#else
380
  WINPR_UNUSED(item);
381
  return FALSE;
382
#endif
383
0
}
384
385
WINPR_JSON* WINPR_JSON_CreateNull(void)
386
0
{
387
0
#if defined(WITH_JSONC)
388
0
  return json_object_new_null();
389
#elif defined(WITH_CJSON)
390
  return cJSON_CreateNull();
391
#else
392
  return NULL;
393
#endif
394
0
}
395
396
WINPR_JSON* WINPR_JSON_CreateTrue(void)
397
0
{
398
0
#if defined(WITH_JSONC)
399
0
  return json_object_new_boolean(TRUE);
400
#elif defined(WITH_CJSON)
401
  return cJSON_CreateTrue();
402
#else
403
  return NULL;
404
#endif
405
0
}
406
407
WINPR_JSON* WINPR_JSON_CreateFalse(void)
408
0
{
409
0
#if defined(WITH_JSONC)
410
0
  return json_object_new_boolean(FALSE);
411
#elif defined(WITH_CJSON)
412
  return cJSON_CreateFalse();
413
#else
414
  return NULL;
415
#endif
416
0
}
417
418
WINPR_JSON* WINPR_JSON_CreateBool(BOOL boolean)
419
0
{
420
0
#if defined(WITH_JSONC)
421
0
  return json_object_new_boolean(boolean);
422
#elif defined(WITH_CJSON)
423
  return cJSON_CreateBool(boolean);
424
#else
425
  WINPR_UNUSED(boolean);
426
  return NULL;
427
#endif
428
0
}
429
430
WINPR_JSON* WINPR_JSON_CreateNumber(double num)
431
0
{
432
0
#if defined(WITH_JSONC)
433
0
  return json_object_new_double(num);
434
#elif defined(WITH_CJSON)
435
  return cJSON_CreateNumber(num);
436
#else
437
  WINPR_UNUSED(num);
438
  return NULL;
439
#endif
440
0
}
441
442
WINPR_JSON* WINPR_JSON_CreateString(const char* string)
443
0
{
444
0
#if defined(WITH_JSONC)
445
0
  return json_object_new_string(string);
446
#elif defined(WITH_CJSON)
447
  return cJSON_CreateString(string);
448
#else
449
  WINPR_UNUSED(string);
450
  return NULL;
451
#endif
452
0
}
453
454
WINPR_JSON* WINPR_JSON_CreateArray(void)
455
0
{
456
0
#if defined(WITH_JSONC)
457
0
  return json_object_new_array();
458
#elif defined(WITH_CJSON)
459
  return cJSON_CreateArray();
460
#else
461
  return NULL;
462
#endif
463
0
}
464
465
WINPR_JSON* WINPR_JSON_CreateObject(void)
466
0
{
467
0
#if defined(WITH_JSONC)
468
0
  return json_object_new_object();
469
#elif defined(WITH_CJSON)
470
  return cJSON_CreateObject();
471
#else
472
  return NULL;
473
#endif
474
0
}
475
476
WINPR_JSON* WINPR_JSON_AddNullToObject(WINPR_JSON* object, const char* name)
477
0
{
478
0
#if defined(WITH_JSONC)
479
0
  struct json_object* obj = json_object_new_null();
480
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
481
0
  {
482
0
    json_object_put(obj);
483
0
    return NULL;
484
0
  }
485
0
  return obj;
486
#elif defined(WITH_CJSON)
487
  return cJSON_AddNullToObject((cJSON*)object, name);
488
#else
489
  WINPR_UNUSED(object);
490
  WINPR_UNUSED(name);
491
  return NULL;
492
#endif
493
0
}
494
495
WINPR_JSON* WINPR_JSON_AddTrueToObject(WINPR_JSON* object, const char* name)
496
0
{
497
0
#if defined(WITH_JSONC)
498
0
  struct json_object* obj = json_object_new_boolean(TRUE);
499
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
500
0
  {
501
0
    json_object_put(obj);
502
0
    return NULL;
503
0
  }
504
0
  return obj;
505
#elif defined(WITH_CJSON)
506
  return cJSON_AddTrueToObject((cJSON*)object, name);
507
#else
508
  WINPR_UNUSED(object);
509
  WINPR_UNUSED(name);
510
  return NULL;
511
#endif
512
0
}
513
514
WINPR_JSON* WINPR_JSON_AddFalseToObject(WINPR_JSON* object, const char* name)
515
0
{
516
0
#if defined(WITH_JSONC)
517
0
  struct json_object* obj = json_object_new_boolean(FALSE);
518
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
519
0
  {
520
0
    json_object_put(obj);
521
0
    return NULL;
522
0
  }
523
0
  return obj;
524
#elif defined(WITH_CJSON)
525
  return cJSON_AddFalseToObject((cJSON*)object, name);
526
#else
527
  WINPR_UNUSED(object);
528
  WINPR_UNUSED(name);
529
  return NULL;
530
#endif
531
0
}
532
533
WINPR_JSON* WINPR_JSON_AddBoolToObject(WINPR_JSON* object, const char* name, BOOL boolean)
534
0
{
535
0
#if defined(WITH_JSONC)
536
0
  struct json_object* obj = json_object_new_boolean(boolean);
537
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
538
0
  {
539
0
    json_object_put(obj);
540
0
    return NULL;
541
0
  }
542
0
  return obj;
543
#elif defined(WITH_CJSON)
544
  return cJSON_AddBoolToObject((cJSON*)object, name, boolean);
545
#else
546
  WINPR_UNUSED(object);
547
  WINPR_UNUSED(name);
548
  WINPR_UNUSED(boolean);
549
  return NULL;
550
#endif
551
0
}
552
553
WINPR_JSON* WINPR_JSON_AddNumberToObject(WINPR_JSON* object, const char* name, double number)
554
0
{
555
0
#if defined(WITH_JSONC)
556
0
  struct json_object* obj = json_object_new_double(number);
557
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
558
0
  {
559
0
    json_object_put(obj);
560
0
    return NULL;
561
0
  }
562
0
  return obj;
563
#elif defined(WITH_CJSON)
564
  return cJSON_AddNumberToObject((cJSON*)object, name, number);
565
#else
566
  WINPR_UNUSED(object);
567
  WINPR_UNUSED(name);
568
  WINPR_UNUSED(number);
569
  return NULL;
570
#endif
571
0
}
572
573
WINPR_JSON* WINPR_JSON_AddStringToObject(WINPR_JSON* object, const char* name, const char* string)
574
0
{
575
0
#if defined(WITH_JSONC)
576
0
  struct json_object* obj = json_object_new_string(string);
577
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
578
0
  {
579
0
    json_object_put(obj);
580
0
    return NULL;
581
0
  }
582
0
  return obj;
583
#elif defined(WITH_CJSON)
584
  return cJSON_AddStringToObject((cJSON*)object, name, string);
585
#else
586
  WINPR_UNUSED(object);
587
  WINPR_UNUSED(name);
588
  WINPR_UNUSED(string);
589
  return NULL;
590
#endif
591
0
}
592
593
WINPR_JSON* WINPR_JSON_AddObjectToObject(WINPR_JSON* object, const char* name)
594
0
{
595
0
#if defined(WITH_JSONC)
596
0
  struct json_object* obj = json_object_new_object();
597
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
598
0
  {
599
0
    json_object_put(obj);
600
0
    return NULL;
601
0
  }
602
0
  return obj;
603
#elif defined(WITH_CJSON)
604
  return cJSON_AddObjectToObject((cJSON*)object, name);
605
#else
606
  WINPR_UNUSED(object);
607
  WINPR_UNUSED(name);
608
  return NULL;
609
#endif
610
0
}
611
612
BOOL WINPR_JSON_AddItemToArray(WINPR_JSON* array, WINPR_JSON* item)
613
0
{
614
0
#if defined(WITH_JSONC)
615
0
  const int rc = json_object_array_add((json_object*)array, (json_object*)item);
616
0
  if (rc != 0)
617
0
    return FALSE;
618
0
  return TRUE;
619
#elif defined(WITH_CJSON)
620
#if defined(USE_CJSON_COMPAT)
621
  if ((array == NULL) || (item == NULL))
622
    return FALSE;
623
  cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
624
  return TRUE;
625
#else
626
  return cJSON_AddItemToArray((cJSON*)array, (cJSON*)item);
627
#endif
628
#else
629
  WINPR_UNUSED(array);
630
  WINPR_UNUSED(item);
631
  return FALSE;
632
#endif
633
0
}
634
635
WINPR_JSON* WINPR_JSON_AddArrayToObject(WINPR_JSON* object, const char* name)
636
0
{
637
0
#if defined(WITH_JSONC)
638
0
  struct json_object* obj = json_object_new_array();
639
0
  if (json_object_object_add((json_object*)object, name, obj) != 0)
640
0
  {
641
0
    json_object_put(obj);
642
0
    return NULL;
643
0
  }
644
0
  return obj;
645
#elif defined(WITH_CJSON)
646
  return cJSON_AddArrayToObject((cJSON*)object, name);
647
#else
648
  WINPR_UNUSED(object);
649
  WINPR_UNUSED(name);
650
  return NULL;
651
#endif
652
0
}
653
654
char* WINPR_JSON_Print(WINPR_JSON* item)
655
0
{
656
0
#if defined(WITH_JSONC)
657
0
  const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PRETTY);
658
0
  if (!str)
659
0
    return NULL;
660
0
  return _strdup(str);
661
#elif defined(WITH_CJSON)
662
  return cJSON_Print((const cJSON*)item);
663
#else
664
  WINPR_UNUSED(item);
665
  return NULL;
666
#endif
667
0
}
668
669
char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item)
670
0
{
671
0
#if defined(WITH_JSONC)
672
0
  const char* str = json_object_to_json_string_ext((json_object*)item, JSON_C_TO_STRING_PLAIN);
673
0
  if (!str)
674
0
    return NULL;
675
0
  return _strdup(str);
676
#elif defined(WITH_CJSON)
677
  return cJSON_PrintUnformatted((const cJSON*)item);
678
#else
679
  WINPR_UNUSED(item);
680
  return NULL;
681
#endif
682
0
}
683
684
WINPR_JSON* WINPR_JSON_ParseFromFile(const char* filename)
685
0
{
686
0
  FILE* fp = winpr_fopen(filename, "r");
687
0
  if (!fp)
688
0
    return NULL;
689
0
  WINPR_JSON* json = WINPR_JSON_ParseFromFileFP(fp);
690
0
  (void)fclose(fp);
691
0
  return json;
692
0
}
693
694
WINPR_JSON* WINPR_JSON_ParseFromFileFP(FILE* fp)
695
0
{
696
0
  if (!fp)
697
0
    return NULL;
698
699
0
  if (fseek(fp, 0, SEEK_END) != 0)
700
0
    return NULL;
701
702
0
  const INT64 size = _ftelli64(fp);
703
0
  if (size < 0)
704
0
    return NULL;
705
706
0
  if (fseek(fp, 0, SEEK_SET) != 0)
707
0
    return NULL;
708
709
0
  const size_t usize = WINPR_ASSERTING_INT_CAST(size_t, size);
710
0
  char* str = calloc(usize + 1, sizeof(char));
711
0
  if (!str)
712
0
    return NULL;
713
714
0
  WINPR_JSON* json = NULL;
715
0
  const size_t s = fread(str, sizeof(char), usize, fp);
716
0
  if (s == usize)
717
0
    json = WINPR_JSON_ParseWithLength(str, usize);
718
0
  free(str);
719
0
  return json;
720
0
}