Files
mongoose/src/json.h
T
94xhn dc52d8b1dc fix(json): reject malformed hex input
Reject odd-length and non-hex strings before decoding them.

Tested: 1796 ASan/UBSan tests in amalgamated and unamalgamated builds
2026-07-16 08:33:06 +08:00

92 lines
4.1 KiB
C

#pragma once
#include "arch.h"
#include "str.h"
// Maximum JSON nesting depth. mg_json_get() returns MG_JSON_TOO_DEEP if
// the path traverses more than this many nested objects/arrays.
#ifndef MG_JSON_MAX_DEPTH
#define MG_JSON_MAX_DEPTH 30
#endif
// Error codes returned by mg_json_get(). Successful returns are >= 0.
enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
// Low-level token locator. Finds the JSON token at path inside json and
// returns its byte offset in json.buf. Sets *toklen to the token length.
// toklen may be NULL if only a presence check is needed.
// path must start with "$" (root). Use ".key" for object fields and "[N]"
// for array indices. Example: "$.items[0].name"
// Returns MG_JSON_NOT_FOUND, MG_JSON_INVALID, or MG_JSON_TOO_DEEP on error.
int mg_json_get(struct mg_str json, const char *path, int *toklen);
// Returns the raw JSON token at path.
//
// Returns:
// Zero-copy mg_str slice into json.buf, or {NULL, 0} if not found or invalid.
// Example:
// struct mg_str tok = mg_json_get_tok(body, "$.device.name");
// Full examples:
// src/dash.c
// Related APIs:
// mg_json_get(), mg_json_get_str(), mg_json_unescape()
// Notes:
// The returned token is not NUL-terminated. String tokens include the
// surrounding double quotes and escape sequences; use mg_json_unescape() or
// mg_json_get_str() when you need decoded string content.
struct mg_str mg_json_get_tok(struct mg_str json, const char *path);
// Parses a numeric JSON value at path into *v.
// Returns true and sets *v on success. Returns false if not found or not a
// number. v may be NULL to check existence only.
bool mg_json_get_num(struct mg_str json, const char *path, double *v);
// Parses a boolean JSON value at path into *v.
// Returns true and sets *v on success. Returns false if not found or not a
// boolean literal. v may be NULL to check existence only.
bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);
// Returns a JSON number at path as a long, or dflt if not found or not a
// number. Use mg_json_get_num() when you need to distinguish missing from 0.
long mg_json_get_long(struct mg_str json, const char *path, long dflt);
// Returns a heap-allocated, NUL-terminated, JSON-unescaped copy of the string
// at path. Caller must mg_free() the result. Returns NULL if not found or the
// token is not a JSON string.
char *mg_json_get_str(struct mg_str json, const char *path);
// Decodes a hex-encoded JSON string at path into a heap-allocated byte array.
// Sets *len to the decoded byte count. Caller must mg_free() the result.
// Returns NULL if not found, not a string, or not valid hexadecimal.
char *mg_json_get_hex(struct mg_str json, const char *path, int *len);
// Decodes a base64-encoded JSON string at path into a heap-allocated byte
// array. Sets *len to the decoded byte count. Caller must mg_free() the result.
// Returns NULL if not found or not a string.
char *mg_json_get_b64(struct mg_str json, const char *path, int *len);
// Writes a JSON-unescaped string value at path into a caller-supplied buffer.
//
// Returns:
// Number of bytes written excluding the NUL, or 0 on error, not found,
// non-string token, too-small buffer, or an empty string.
// Example:
// char name[32];
// mg_json_unescape(body, "$.device.name", name, sizeof(name));
// Full examples:
// src/dash.c, src/ota.c
// Related APIs:
// mg_json_get_tok(), mg_json_get_str(), mg_json_get_num()
// Notes:
// On success, NUL-terminates when n > 0. The destination buffer is owned by
// the caller. Only string tokens are unescaped; other token types return 0.
size_t mg_json_unescape(struct mg_str json, const char *path, char *, size_t);
// Sequential iterator over a JSON object or array. Start with ofs=0.
// Each call fills *key and *val with the next entry and returns the new ofs
// to pass on the next call. Returns 0 when there are no more entries.
// For arrays, *key is set to {NULL, 0}. For objects, *key is the raw
// quoted key (e.g. "\"name\""). *val is the raw unparsed token.
size_t mg_json_next(struct mg_str obj, size_t ofs, struct mg_str *key,
struct mg_str *val);