Skip to content

Commit 79b844c

Browse files
committed
JSON parser CHANGE respect STRICT flag and if not set, ignore unknown data
Fixes #895
1 parent 7f9f713 commit 79b844c

File tree

1 file changed

+87
-2
lines changed

1 file changed

+87
-2
lines changed

src/parser_json.c

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,83 @@ store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first,
773773
return -1;
774774
}
775775

776+
/**
777+
* @brief Skip subtree (find its end in the input data) of the current JSON item.
778+
* @param[in] ctx libyang context for logging
779+
* @param[in] parent parent node for logging
780+
* @param[in] data input data (pointing to the beginning, @p len is used to go to the current position).
781+
* @param[in, out] len Current position in the @p data, will be updated to the end of the element's subtree in the @p data
782+
* @retun 0 on success
783+
* @return -1 on error.
784+
*/
785+
static int
786+
json_skip_unknown(struct ly_ctx *ctx, struct lyd_node *parent, const char *data, unsigned int *len)
787+
{
788+
int qstr = 0;
789+
int objects = 0;
790+
int arrays = 0;
791+
792+
while (data[*len]) {
793+
switch (data[*len]) {
794+
case '\"':
795+
if (qstr) {
796+
if (data[(*len) - 1] != '\\') {
797+
qstr = 0;
798+
}
799+
} else if (data[(*len) - 1] != '\\') {
800+
qstr = 1;
801+
} else {
802+
LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, parent, "JSON data (missing quotation mark for a string data) ");
803+
return -1;
804+
}
805+
break;
806+
case '[':
807+
if (!qstr) {
808+
arrays++;
809+
}
810+
break;
811+
case '{':
812+
if (!qstr) {
813+
objects++;
814+
}
815+
break;
816+
case ']':
817+
if (!qstr) {
818+
arrays--;
819+
}
820+
break;
821+
case '}':
822+
if (!qstr) {
823+
objects--;
824+
}
825+
break;
826+
case ',':
827+
if (!qstr && !objects && !arrays) {
828+
/* do not eat the comma character */
829+
return 0;
830+
}
831+
}
832+
833+
if (objects < 0) {
834+
if (arrays) {
835+
LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, parent, "JSON data (missing end-array)");
836+
return -1;
837+
}
838+
return 0;
839+
}
840+
if (arrays < 0) {
841+
if (objects) {
842+
LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, parent, "JSON data (missing end-object)");
843+
return -1;
844+
}
845+
return 0;
846+
}
847+
(*len)++;
848+
}
849+
850+
return 0;
851+
}
852+
776853
static unsigned int
777854
json_parse_data(struct ly_ctx *ctx, const char *data, const struct lys_node *schema_parent, struct lyd_node **parent,
778855
struct lyd_node *first_sibling, struct lyd_node *prev, struct attr_cont **attrs, int options,
@@ -943,8 +1020,16 @@ json_parse_data(struct ly_ctx *ctx, const char *data, const struct lys_node *sch
9431020

9441021
module = lys_node_module(schema);
9451022
if (!module || !module->implemented || module->disabled) {
946-
LOGVAL(ctx, LYE_INELEM, (*parent ? LY_VLOG_LYD : LY_VLOG_NONE), (*parent), name);
947-
goto error;
1023+
if (options & LYD_OPT_STRICT) {
1024+
LOGVAL(ctx, LYE_INELEM, (*parent ? LY_VLOG_LYD : LY_VLOG_NONE), (*parent), name);
1025+
goto error;
1026+
} else {
1027+
if (json_skip_unknown(ctx, *parent, data, &len)) {
1028+
goto error;
1029+
}
1030+
free(str);
1031+
return len;
1032+
}
9481033
}
9491034

9501035
if (str[0] == '@') {

0 commit comments

Comments
 (0)