Skip to content

Commit a74e422

Browse files
committed
data: option to loosen json data type validation
Prior to v1.0.212 the default behavior was to allow numbers and boolean values to be in quotes, which is technically a violation of the spec. This adds a new `LY_CTX_LOOSE_JSON_DATATYPES` context option which will restore the prior behavior when enabled. SONiC is using v1.0.73 currently and has a large installed base which may be in violation of the new behavior, so adding such a flag is required for this usecase. Signed-off-by: Brad House <[email protected]>
1 parent 03e294d commit a74e422

24 files changed

+37
-29
lines changed

src/context.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ struct ly_ctx;
207207
loaded except for built-in YANG types so all derived types will use these and
208208
for all purposes behave as the base type. The option can be used for cases when
209209
invalid data needs to be stored in YANG node values. */
210+
#define LY_CTX_LOOSE_JSON_DATATYPES 0x1000 /**< By default, JSON data values are validated to be in the proper format. For
211+
instance numbers are expected to not be enclosed in quotes, nor are boolean
212+
values. Setting this context option will disable this validation. Prior to
213+
v1.0.212 this was the default behavior. */
210214

211215
/** @} contextoptions */
212216

src/plugins_types.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,8 @@ type_get_hints_base(uint32_t hints)
666666
}
667667

668668
LIBYANG_API_DEF LY_ERR
669-
lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_DATA_TYPE type, int *base,
670-
struct ly_err_item **err)
669+
lyplg_type_check_hints(const struct ly_ctx *ctx, uint32_t hints, const char *value, size_t value_len,
670+
LY_DATA_TYPE type, int *base, struct ly_err_item **err)
671671
{
672672
LY_CHECK_ARG_RET(NULL, value || !value_len, err, LY_EINVAL);
673673

@@ -685,7 +685,8 @@ lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_D
685685
case LY_TYPE_INT32:
686686
LY_CHECK_ARG_RET(NULL, base, LY_EINVAL);
687687

688-
if (!(hints & (LYD_VALHINT_DECNUM | LYD_VALHINT_OCTNUM | LYD_VALHINT_HEXNUM))) {
688+
if (!(hints & (LYD_VALHINT_DECNUM | LYD_VALHINT_OCTNUM | LYD_VALHINT_HEXNUM)) &&
689+
!(ly_ctx_get_options(ctx) & LY_CTX_LOOSE_JSON_DATATYPES)) {
689690
return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid non-number-encoded %s value \"%.*s\".",
690691
lys_datatype2str(type), (int)value_len, value);
691692
}
@@ -695,7 +696,8 @@ lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_D
695696
case LY_TYPE_INT64:
696697
LY_CHECK_ARG_RET(NULL, base, LY_EINVAL);
697698

698-
if (!(hints & LYD_VALHINT_NUM64)) {
699+
if (!(hints & LYD_VALHINT_NUM64) &&
700+
!(ly_ctx_get_options(ctx) & LY_CTX_LOOSE_JSON_DATATYPES)) {
699701
return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid non-num64-encoded %s value \"%.*s\".",
700702
lys_datatype2str(type), (int)value_len, value);
701703
}
@@ -714,7 +716,8 @@ lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_D
714716
}
715717
break;
716718
case LY_TYPE_BOOL:
717-
if (!(hints & LYD_VALHINT_BOOLEAN)) {
719+
if (!(hints & LYD_VALHINT_BOOLEAN) &&
720+
!(ly_ctx_get_options(ctx) & LY_CTX_LOOSE_JSON_DATATYPES)) {
718721
return ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid non-boolean-encoded %s value \"%.*s\".",
719722
lys_datatype2str(type), (int)value_len, value);
720723
}

src/plugins_types.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ LIBYANG_API_DECL void ly_err_free(void *ptr);
243243
*
244244
* Use only in implementations of ::lyplg_type_store_clb which provide all the necessary parameters for this function.
245245
*
246+
* @param[in] ctx libyang context.
246247
* @param[in] hints Bitmap of [value hints](@ref lydvalhints) of all the allowed value types provided by parsers
247248
* to ::lyplg_type_store_clb.
248249
* @param[in] value Lexical representation of the value to be stored.
@@ -253,8 +254,8 @@ LIBYANG_API_DECL void ly_err_free(void *ptr);
253254
* @param[out] err Pointer to store error information in case of failure.
254255
* @return LY_ERR value
255256
*/
256-
LIBYANG_API_DECL LY_ERR lyplg_type_check_hints(uint32_t hints, const char *value, size_t value_len, LY_DATA_TYPE type,
257-
int *base, struct ly_err_item **err);
257+
LIBYANG_API_DECL LY_ERR lyplg_type_check_hints(const struct ly_ctx *ctx, uint32_t hints, const char *value,
258+
size_t value_len, LY_DATA_TYPE type, int *base, struct ly_err_item **err);
258259

259260
/**
260261
* @brief Check that the value of a type is allowed based on its status.

src/plugins_types/binary.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ lyplg_type_store_binary(const struct ly_ctx *ctx, const struct lysc_type *type,
289289
}
290290

291291
/* check hints */
292-
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
292+
ret = lyplg_type_check_hints(ctx, hints, value, value_len, type->basetype, NULL, err);
293293
LY_CHECK_GOTO(ret, cleanup);
294294

295295
if (format != LY_VALUE_CANON) {

src/plugins_types/bits.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ lyplg_type_store_bits(const struct ly_ctx *ctx, const struct lysc_type *type, co
328328
}
329329

330330
/* check hints */
331-
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
331+
ret = lyplg_type_check_hints(ctx, hints, value, value_len, type->basetype, NULL, err);
332332
LY_CHECK_GOTO(ret, cleanup);
333333

334334
/* allocate the bitmap */

src/plugins_types/boolean.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ lyplg_type_store_boolean(const struct ly_ctx *ctx, const struct lysc_type *type,
6767
}
6868

6969
/* check hints */
70-
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
70+
ret = lyplg_type_check_hints(ctx, hints, value, value_len, type->basetype, NULL, err);
7171
LY_CHECK_GOTO(ret, cleanup);
7272

7373
/* validate and store the value */

src/plugins_types/date_and_time.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ lyplg_type_store_date_and_time(const struct ly_ctx *ctx, const struct lysc_type
9898
}
9999

100100
/* check hints */
101-
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
101+
ret = lyplg_type_check_hints(ctx, hints, value, value_len, type->basetype, NULL, err);
102102
LY_CHECK_GOTO(ret, cleanup);
103103

104104
/* convert to UNIX time and fractions of second, function must check for all the possible errors */

src/plugins_types/decimal64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ lyplg_type_store_decimal64(const struct ly_ctx *ctx, const struct lysc_type *typ
108108
num = le64toh(num);
109109
} else {
110110
/* check hints */
111-
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
111+
ret = lyplg_type_check_hints(ctx, hints, value, value_len, type->basetype, NULL, err);
112112
LY_CHECK_GOTO(ret, cleanup);
113113

114114
/* parse decimal64 value */

src/plugins_types/empty.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ lyplg_type_store_empty(const struct ly_ctx *ctx, const struct lysc_type *type, c
4646
storage->realtype = type;
4747

4848
/* check hints */
49-
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
49+
ret = lyplg_type_check_hints(ctx, hints, value, value_len, type->basetype, NULL, err);
5050
LY_CHECK_GOTO(ret, cleanup);
5151

5252
/* validation */

src/plugins_types/enumeration.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ lyplg_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, co
9292
}
9393

9494
/* check hints */
95-
ret = lyplg_type_check_hints(hints, value, value_len, type->basetype, NULL, err);
95+
ret = lyplg_type_check_hints(ctx, hints, value, value_len, type->basetype, NULL, err);
9696
LY_CHECK_GOTO(ret, cleanup);
9797

9898
/* find the matching enumeration value item */

0 commit comments

Comments
 (0)