/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 |