Coverage Report

Created: 2025-08-05 08:11

/src/osquery/osquery/utils/json/json.cpp
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Copyright (c) 2014-present, The osquery authors
3
 *
4
 * This source code is licensed as defined by the LICENSE file found in the
5
 * root directory of this source tree.
6
 *
7
 * SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
8
 */
9
10
#include "json.h"
11
12
#include <osquery/utils/conversions/tryto.h>
13
14
#include <algorithm>
15
16
namespace rj = rapidjson;
17
18
namespace osquery {
19
20
66.9k
JSON::JSON(rj::Type type) : type_(type) {
21
66.9k
  if (type_ == rj::kObjectType) {
22
66.9k
    doc_.SetObject();
23
66.9k
  } else {
24
0
    doc_.SetArray();
25
0
  }
26
66.9k
}
27
28
57.5k
JSON::JSON() {
29
57.5k
  type_ = rj::kObjectType;
30
57.5k
  doc_.SetObject();
31
57.5k
}
32
33
66.9k
JSON JSON::newObject() {
34
66.9k
  return JSON(rj::kObjectType);
35
66.9k
}
36
37
0
JSON JSON::newArray() {
38
0
  return JSON(rj::kArrayType);
39
0
}
40
41
21.6k
rj::Document JSON::getObject() const {
42
21.6k
  rj::Document line;
43
21.6k
  line.SetObject();
44
21.6k
  return line;
45
21.6k
}
46
47
522
rj::Document JSON::getArray() const {
48
522
  rj::Document line;
49
522
  line.SetArray();
50
522
  return line;
51
522
}
52
53
0
void JSON::push(rj::Value& value) {
54
0
  assert(type_ == rj::kArrayType);
55
0
  push(value, doc());
56
0
}
57
58
140
void JSON::push(rj::Value& value, rj::Value& arr) {
59
140
  arr.PushBack(rj::Value(value, doc_.GetAllocator()).Move(),
60
140
               doc_.GetAllocator());
61
140
}
62
63
0
void JSON::push(size_t value) {
64
0
  push(value, doc());
65
0
}
66
67
0
void JSON::push(size_t value, rj::Value& arr) {
68
0
  arr.PushBack(rj::Value(static_cast<uint64_t>(value)).Move(),
69
0
               doc_.GetAllocator());
70
0
}
71
72
0
void JSON::pushCopy(const std::string& value) {
73
0
  pushCopy(value, doc());
74
0
}
75
76
243k
void JSON::pushCopy(const std::string& value, rj::Value& arr) {
77
243k
  rj::Value sc;
78
243k
  sc.SetString(value.c_str(), value.size(), doc_.GetAllocator());
79
243k
  arr.PushBack(sc.Move(), doc_.GetAllocator());
80
243k
}
81
82
16.4k
void JSON::add(const std::string& key, const rj::Value& value) {
83
16.4k
  add(key, value, doc());
84
16.4k
}
85
86
16.7k
void JSON::add(const std::string& key, const rj::Value& value, rj::Value& obj) {
87
16.7k
  assert(obj.IsObject());
88
16.7k
  auto itr = obj.FindMember(key);
89
16.7k
  if (itr != obj.MemberEnd()) {
90
3.59k
    obj.RemoveMember(itr);
91
3.59k
  }
92
93
16.7k
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
94
16.7k
                rj::Value(value, doc_.GetAllocator()).Move(),
95
16.7k
                doc_.GetAllocator());
96
16.7k
}
97
98
void JSON::addCopy(const std::string& key,
99
                   const std::string& value,
100
70
                   rj::Value& obj) {
101
70
  assert(obj.IsObject());
102
70
  auto itr = obj.FindMember(key);
103
70
  if (itr != obj.MemberEnd()) {
104
0
    obj.RemoveMember(itr);
105
0
  }
106
107
70
  rj::Value sc;
108
70
  sc.SetString(value.c_str(), value.size(), doc_.GetAllocator());
109
70
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
110
70
                sc.Move(),
111
70
                doc_.GetAllocator());
112
70
}
113
114
0
void JSON::addCopy(const std::string& key, const std::string& value) {
115
0
  addCopy(key, value, doc());
116
0
}
117
118
void JSON::addRef(const std::string& key,
119
                  const std::string& value,
120
140
                  rj::Value& obj) {
121
140
  assert(obj.IsObject());
122
140
  auto itr = obj.FindMember(key);
123
140
  if (itr != obj.MemberEnd()) {
124
0
    obj.RemoveMember(itr);
125
0
  }
126
127
140
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
128
140
                rj::Value(rj::StringRef(value), doc_.GetAllocator()).Move(),
129
140
                doc_.GetAllocator());
130
140
}
131
132
0
void JSON::addRef(const std::string& key, const std::string& value) {
133
0
  addRef(key, value, doc());
134
0
}
135
136
0
void JSON::add(const std::string& key, const std::string& value) {
137
0
  addCopy(key, value);
138
0
}
139
140
void JSON::add(const std::string& key,
141
               const std::string& value,
142
0
               rj::Value& obj) {
143
0
  addCopy(key, value, obj);
144
0
}
145
146
0
void JSON::add(const std::string& key, const char* value, rj::Value& obj) {
147
0
  assert(obj.IsObject());
148
0
  auto itr = obj.FindMember(key);
149
0
  if (itr != obj.MemberEnd()) {
150
0
    obj.RemoveMember(itr);
151
0
  }
152
153
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
154
0
                rj::Value(value, strlen(value)).Move(),
155
0
                doc_.GetAllocator());
156
0
}
157
0
void JSON::add(const std::string& key, const char* value) {
158
0
  add(key, value, doc());
159
0
}
160
161
0
void JSON::add(const std::string& key, int value, rj::Value& obj) {
162
0
  assert(obj.IsObject());
163
0
  auto itr = obj.FindMember(key);
164
0
  if (itr != obj.MemberEnd()) {
165
0
    obj.RemoveMember(itr);
166
0
  }
167
168
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
169
0
                rj::Value(static_cast<int64_t>(value)).Move(),
170
0
                doc_.GetAllocator());
171
0
}
172
173
0
void JSON::add(const std::string& key, int value) {
174
0
  add(key, value, doc());
175
0
}
176
177
0
void JSON::add(const std::string& key, long value, rj::Value& obj) {
178
0
  assert(obj.IsObject());
179
0
  auto itr = obj.FindMember(key);
180
0
  if (itr != obj.MemberEnd()) {
181
0
    obj.RemoveMember(itr);
182
0
  }
183
184
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
185
0
                rj::Value(static_cast<int64_t>(value)).Move(),
186
0
                doc_.GetAllocator());
187
0
}
188
189
0
void JSON::add(const std::string& key, long value) {
190
0
  add(key, value, doc());
191
0
}
192
193
0
void JSON::add(const std::string& key, long long value, rj::Value& obj) {
194
0
  assert(obj.IsObject());
195
0
  auto itr = obj.FindMember(key);
196
0
  if (itr != obj.MemberEnd()) {
197
0
    obj.RemoveMember(itr);
198
0
  }
199
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
200
0
                rj::Value(static_cast<int64_t>(value)).Move(),
201
0
                doc_.GetAllocator());
202
0
}
203
0
void JSON::add(const std::string& key, long long value) {
204
0
  add(key, value, doc());
205
0
}
206
207
0
void JSON::add(const std::string& key, unsigned int value, rj::Value& obj) {
208
0
  assert(obj.IsObject());
209
0
  auto itr = obj.FindMember(key);
210
0
  if (itr != obj.MemberEnd()) {
211
0
    obj.RemoveMember(itr);
212
0
  }
213
214
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
215
0
                rj::Value(static_cast<uint64_t>(value)).Move(),
216
0
                doc_.GetAllocator());
217
0
}
218
219
0
void JSON::add(const std::string& key, unsigned int value) {
220
0
  add(key, value, doc());
221
0
}
222
223
70
void JSON::add(const std::string& key, unsigned long value, rj::Value& obj) {
224
70
  assert(obj.IsObject());
225
70
  auto itr = obj.FindMember(key);
226
70
  if (itr != obj.MemberEnd()) {
227
0
    obj.RemoveMember(itr);
228
0
  }
229
230
70
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
231
70
                rj::Value(static_cast<uint64_t>(value)).Move(),
232
70
                doc_.GetAllocator());
233
70
}
234
235
0
void JSON::add(const std::string& key, unsigned long value) {
236
0
  add(key, value, doc());
237
0
}
238
239
void JSON::add(const std::string& key,
240
               unsigned long long value,
241
0
               rj::Value& obj) {
242
0
  assert(obj.IsObject());
243
0
  auto itr = obj.FindMember(key);
244
0
  if (itr != obj.MemberEnd()) {
245
0
    obj.RemoveMember(itr);
246
0
  }
247
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
248
0
                rj::Value(static_cast<uint64_t>(value)).Move(),
249
0
                doc_.GetAllocator());
250
0
}
251
0
void JSON::add(const std::string& key, unsigned long long value) {
252
0
  add(key, value, doc());
253
0
}
254
0
void JSON::add(const std::string& key, double value, rj::Value& obj) {
255
0
  assert(obj.IsObject());
256
0
  auto itr = obj.FindMember(key);
257
0
  if (itr != obj.MemberEnd()) {
258
0
    obj.RemoveMember(itr);
259
0
  }
260
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
261
0
                rj::Value(value).Move(),
262
0
                doc_.GetAllocator());
263
0
}
264
0
void JSON::add(const std::string& key, double value) {
265
0
  add(key, value, doc());
266
0
}
267
268
0
void JSON::add(const std::string& key, bool value, rj::Value& obj) {
269
0
  assert(obj.IsObject());
270
0
  auto itr = obj.FindMember(key);
271
0
  if (itr != obj.MemberEnd()) {
272
0
    obj.RemoveMember(itr);
273
0
  }
274
275
0
  obj.AddMember(rj::Value(rj::StringRef(key), doc_.GetAllocator()).Move(),
276
0
                rj::Value(value).Move(),
277
0
                doc_.GetAllocator());
278
0
}
279
280
0
void JSON::add(const std::string& key, bool value) {
281
0
  add(key, value, doc());
282
0
}
283
284
30.1k
Status JSON::toString(std::string& str) const {
285
30.1k
  rj::StringBuffer sb;
286
30.1k
  rj::Writer<rj::StringBuffer> writer(sb);
287
30.1k
  doc_.Accept(writer);
288
30.1k
  str = sb.GetString();
289
30.1k
  return Status::success();
290
30.1k
}
291
292
0
Status JSON::toPrettyString(std::string& str, size_t indentCharCount) const {
293
0
  rj::StringBuffer sb;
294
0
  rj::PrettyWriter<rj::StringBuffer> writer(sb);
295
0
  writer.SetIndent(' ', indentCharCount);
296
0
  doc_.Accept(writer);
297
0
  str = sb.GetString();
298
0
  return Status::success();
299
0
}
300
301
461
Status JSON::fromString(const std::string& str, ParseMode mode) {
302
461
  rj::ParseResult pr;
303
461
  switch (mode) {
304
391
  case ParseMode::Iterative: {
305
391
    pr = doc_.Parse<rj::kParseIterativeFlag>(str.c_str());
306
391
    break;
307
0
  }
308
70
  case ParseMode::Recursive: {
309
70
    pr = doc_.Parse(str.c_str());
310
70
    break;
311
0
  }
312
461
  }
313
314
461
  if (!pr) {
315
53
    std::string message{"Cannot parse JSON: "};
316
53
    message += GetParseError_En(pr.Code());
317
53
    message += " Offset: ";
318
53
    message += std::to_string(pr.Offset());
319
53
    return Status(1, message);
320
53
  }
321
408
  return Status::success();
322
461
}
323
324
5.28k
void JSON::mergeObject(rj::Value& target_obj, rj::Value& source_obj) {
325
5.28k
  assert(target_obj.IsObject());
326
5.28k
  assert(source_obj.IsObject());
327
10.9k
  for (auto itr = source_obj.MemberBegin(); itr != source_obj.MemberEnd();
328
5.70k
       ++itr) {
329
5.70k
    auto titr = target_obj.FindMember(itr->name);
330
5.70k
    if (titr != target_obj.MemberEnd()) {
331
5.39k
      target_obj.RemoveMember(titr);
332
5.39k
    }
333
334
5.70k
    target_obj.AddMember(itr->name, itr->value, doc_.GetAllocator());
335
5.70k
  }
336
5.28k
}
337
338
0
void JSON::mergeArray(rj::Value& target_arr, rj::Value& source_arr) {
339
0
  assert(target_arr.IsArray());
340
0
  assert(source_arr.IsArray());
341
0
  for (auto itr = source_arr.Begin(); itr != source_arr.End(); ++itr) {
342
0
    target_arr.PushBack(*itr, doc_.GetAllocator());
343
0
  }
344
0
}
345
346
57.5k
JSON JSON::newFromValue(const rj::Value& value) {
347
57.5k
  assert(value.IsObject() || value.IsArray());
348
349
57.5k
  JSON doc;
350
57.5k
  doc.type_ = (value.IsArray()) ? rj::kArrayType : rj::kObjectType;
351
57.5k
  doc.copyFrom(value, doc.doc());
352
57.5k
  return doc;
353
57.5k
}
354
355
132k
void JSON::copyFrom(const rapidjson::Value& value, rj::Value& target) {
356
132k
  target.CopyFrom(value, doc().GetAllocator());
357
132k
}
358
359
53.5k
void JSON::copyFrom(const rj::Value& value) {
360
53.5k
  copyFrom(value, doc());
361
53.5k
}
362
363
395k
rj::Document& JSON::doc() {
364
395k
  return doc_;
365
395k
}
366
367
39.6k
const rj::Document& JSON::doc() const {
368
39.6k
  return doc_;
369
39.6k
}
370
371
15.7k
std::uint64_t JSON::valueToSize(const rj::Value& value) {
372
15.7k
  if (value.IsString()) {
373
3.18k
    return tryTo<std::uint64_t>(std::string{value.GetString()}).takeOr(0_sz);
374
12.5k
  } else if (value.IsNumber()) {
375
12.3k
    return static_cast<size_t>(value.GetUint64());
376
12.3k
  }
377
226
  return 0_sz;
378
15.7k
}
379
380
2.09k
bool JSON::valueToBool(const rj::Value& value) {
381
2.09k
  if (value.IsBool()) {
382
1.84k
    return value.GetBool();
383
1.84k
  } else if (value.IsString()) {
384
243
    auto b = std::string(value.GetString());
385
243
    std::transform(b.begin(), b.end(), b.begin(), ::tolower);
386
387
243
    return (b == "true" || b == "t");
388
243
  } else if (value.IsNumber()) {
389
7
    return (value.GetInt() != 0);
390
7
  }
391
0
  return false;
392
2.09k
}
393
394
0
boost::optional<std::string> JSON::valueToString(const rj::Value& value) {
395
0
  switch (value.GetType()) {
396
0
  case rapidjson::Type::kFalseType: {
397
0
    return std::string{"0"};
398
0
  }
399
0
  case rapidjson::Type::kTrueType: {
400
0
    return std::string{"1"};
401
0
  }
402
0
  case rapidjson::Type::kNumberType: {
403
0
    if (value.IsInt()) {
404
0
      return std::to_string(value.GetInt());
405
0
    } else if (value.IsInt64()) {
406
0
      return std::to_string(value.GetInt64());
407
0
    } else if (value.IsUint()) {
408
0
      return std::to_string(value.GetUint());
409
0
    } else if (value.IsUint64()) {
410
0
      return std::to_string(value.GetUint64());
411
0
    } else if (value.IsDouble()) {
412
0
      return std::to_string(value.GetDouble());
413
0
    }
414
0
    break;
415
0
  }
416
0
  case rapidjson::Type::kStringType: {
417
0
    return std::string{value.GetString()};
418
0
  }
419
0
  case rapidjson::Type::kNullType: {
420
0
    return std::string{"null"};
421
0
  }
422
0
  case rapidjson::Type::kObjectType:
423
0
  case rapidjson::Type::kArrayType: {
424
    // These are not supported, use a Writer instead.
425
0
    break;
426
0
  }
427
0
  }
428
429
0
  return boost::none;
430
0
}
431
432
} // namespace osquery