Skip to content

Commit 552e928

Browse files
authored
Merge pull request #5696 from victormlg/CFE-4163-json
Added optional parameter strict
2 parents ac88b5b + bf81cd0 commit 552e928

File tree

4 files changed

+104
-6
lines changed

4 files changed

+104
-6
lines changed

examples/validdata.cf

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@ bundle agent main
33
{
44
vars:
55
"json_string" string => '{"test": [1, 2, 3]}';
6-
6+
"primitive" string => "\"hello\"";
7+
78
reports:
89
"This JSON string is valid!"
910
if => validdata("$(json_string)", "JSON");
1011
"This JSON string is not valid."
1112
unless => validdata("$(json_string)", "JSON");
13+
14+
"This JSON string is valid! (strict)"
15+
if => validdata("$(primitive)", "JSON", "true");
16+
"This JSON string is not valid. (strict)"
17+
unless => validdata("$(primitive)", "JSON", "true");
1218
}
1319
#+end_src
1420
###############################################################################
1521
#+begin_src example_output
1622
#@ ```
1723
#@ R: This JSON string is valid!
24+
#@ R: This JSON string is not valid. (strict)
1825
#@ ```
1926
#+end_src

examples/validjson.cf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,25 @@ bundle agent main
33
{
44
vars:
55
"json_string" string => '{"test": [1, 2, 3]}';
6+
"primitive" string => "\"hello\"";
67

78
reports:
89
"This JSON string is valid!"
910
if => validjson("$(json_string)");
1011
"This JSON string is not valid."
1112
unless => validjson("$(json_string)");
13+
14+
"This JSON string is valid! (strict)"
15+
if => validjson("$(primitive)", "true");
16+
"This JSON string is not valid. (strict)"
17+
unless => validjson("$(primitive)", "true");
1218
}
19+
1320
#+end_src
1421
###############################################################################
1522
#+begin_src example_output
1623
#@ ```
1724
#@ R: This JSON string is valid!
25+
#@ R: This JSON string is not valid. (strict)
1826
#@ ```
1927
#+end_src

libpromises/evalfunction.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7292,7 +7292,8 @@ static FnCallResult FnCallReadJson(ARG_UNUSED EvalContext *ctx,
72927292

72937293
static FnCallResult ValidateDataGeneric(const char *const fname,
72947294
const char *data,
7295-
const DataFileType requested_mode)
7295+
const DataFileType requested_mode,
7296+
bool strict)
72967297
{
72977298
assert(data != NULL);
72987299
if (requested_mode != DATAFILETYPE_JSON)
@@ -7310,7 +7311,13 @@ static FnCallResult ValidateDataGeneric(const char *const fname,
73107311
Log(LOG_LEVEL_VERBOSE, "%s: %s", fname, JsonParseErrorToString(err));
73117312
}
73127313

7313-
FnCallResult ret = FnReturnContext(json != NULL);
7314+
bool isvalid = json != NULL;
7315+
if (strict)
7316+
{
7317+
isvalid = isvalid && JsonGetElementType(json) != JSON_ELEMENT_TYPE_PRIMITIVE;
7318+
}
7319+
7320+
FnCallResult ret = FnReturnContext(isvalid);
73147321
JsonDestroy(json);
73157322
return ret;
73167323
}
@@ -7326,12 +7333,17 @@ static FnCallResult FnCallValidData(ARG_UNUSED EvalContext *ctx,
73267333
Log(LOG_LEVEL_ERR, "Function '%s' requires two arguments", fp->name);
73277334
return FnFailure();
73287335
}
7336+
bool strict = false;
7337+
if (args->next != NULL)
7338+
{
7339+
strict = BooleanFromString(RlistScalarValue(args->next));
7340+
}
73297341

73307342
const char *data = RlistScalarValue(args);
73317343
const char *const mode_string = RlistScalarValue(args->next);
73327344
DataFileType requested_mode = GetDataFileTypeFromString(mode_string);
73337345

7334-
return ValidateDataGeneric(fp->name, data, requested_mode);
7346+
return ValidateDataGeneric(fp->name, data, requested_mode, strict);
73357347
}
73367348

73377349
static FnCallResult FnCallValidJson(ARG_UNUSED EvalContext *ctx,
@@ -7345,9 +7357,14 @@ static FnCallResult FnCallValidJson(ARG_UNUSED EvalContext *ctx,
73457357
Log(LOG_LEVEL_ERR, "Function '%s' requires one argument", fp->name);
73467358
return FnFailure();
73477359
}
7360+
bool strict = false;
7361+
if (args->next != NULL)
7362+
{
7363+
strict = BooleanFromString(RlistScalarValue(args->next));
7364+
}
73487365

73497366
const char *data = RlistScalarValue(args);
7350-
return ValidateDataGeneric(fp->name, data, DATAFILETYPE_JSON);
7367+
return ValidateDataGeneric(fp->name, data, DATAFILETYPE_JSON, strict);
73517368
}
73527369

73537370
static FnCallResult FnCallReadModuleProtocol(
@@ -9969,6 +9986,7 @@ static const FnCallArg READFILE_ARGS[] =
99699986
static const FnCallArg VALIDDATATYPE_ARGS[] =
99709987
{
99719988
{CF_ANYSTRING, CF_DATA_TYPE_STRING, "String to validate as JSON"},
9989+
{CF_BOOL, CF_DATA_TYPE_OPTION, "Enable more strict validation, requiring the result to be a valid data container, matching the requirements of parsejson()."},
99729990
{NULL, CF_DATA_TYPE_NONE, NULL}
99739991
};
99749992

@@ -10025,6 +10043,7 @@ static const FnCallArg VALIDDATA_ARGS[] =
1002510043
{
1002610044
{CF_ANYSTRING, CF_DATA_TYPE_STRING, "String to validate as JSON"},
1002710045
{"JSON", CF_DATA_TYPE_OPTION, "Type of data to validate"},
10046+
{CF_BOOL, CF_DATA_TYPE_OPTION, "Enable more strict validation, requiring the result to be a valid data container, matching the requirements of parsejson()."},
1002810047
{NULL, CF_DATA_TYPE_NONE, NULL}
1002910048
};
1003010049

@@ -10777,7 +10796,7 @@ const FnCallType CF_FNCALL_TYPES[] =
1077710796
FnCallTypeNew("userexists", CF_DATA_TYPE_CONTEXT, USEREXISTS_ARGS, &FnCallUserExists, "True if user name or numerical id exists on this host",
1077810797
FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL),
1077910798
FnCallTypeNew("validdata", CF_DATA_TYPE_CONTEXT, VALIDDATA_ARGS, &FnCallValidData, "Check for errors in JSON or YAML data",
10780-
FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
10799+
FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
1078110800
FnCallTypeNew("validjson", CF_DATA_TYPE_CONTEXT, VALIDDATATYPE_ARGS, &FnCallValidJson, "Check for errors in JSON data",
1078210801
FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
1078310802
FnCallTypeNew("variablesmatching", CF_DATA_TYPE_STRING_LIST, CLASSMATCH_ARGS, &FnCallVariablesMatching, "List the variables matching regex arg1 and tag regexes arg2,arg3,...",
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
body common control
2+
{
3+
inputs => { "../../default.cf.sub" };
4+
bundlesequence => { test, check };
5+
version => "1.0";
6+
}
7+
8+
bundle agent test
9+
{
10+
meta:
11+
"description" -> { "CFE-4163" }
12+
string => "Test policy strict parameter of validjson and validdata";
13+
}
14+
15+
bundle agent check
16+
{
17+
vars:
18+
"json" string => readfile("$(this.promise_dirname)/validdata.cf.json", inf);
19+
"invjson" string => readfile("$(this.promise_dirname)/validdata.cf.inv.json", inf);
20+
"mystring" string => "\"foo\"";
21+
"mynumber" string => "3.14";
22+
"mybool" string => "true";
23+
"mynull" string => "null";
24+
25+
classes:
26+
"isvalid_json"
27+
expression => validjson("$(json)", "false");
28+
"isinvalid_json"
29+
expression => not(validjson("$(invjson)", "false"));
30+
"isvalid_string_primitive"
31+
expression => validjson("$(mystring)", "false");
32+
"isvalid_number_primitive_strict"
33+
expression => validjson("$(mynumber)", "false");
34+
"isvalid_bool_primitive"
35+
expression => validjson("$(mybool)", "false");
36+
"isvalid_null_primitive"
37+
expression => validjson("$(mynull)", "false");
38+
39+
"invalid_json_strict"
40+
expression => validjson("$(json)", "true");
41+
"isinvalid_json_strict"
42+
expression => not(validjson("$(invjson)", "true"));
43+
"isinvalid_string_primitive_strict"
44+
expression => not(validjson("$(mystring)", "true"));
45+
"isinvalid_number_primitive_strict"
46+
expression => not(validjson("$(mynumber)", "true"));
47+
"isinvalid_bool_primitive_strict"
48+
expression => not(validjson("$(mybool)", "true"));
49+
"isinvalid_null_primitive_strict"
50+
expression => not(validjson("$(mynull)", "true"));
51+
52+
"ok"
53+
and => { "isvalid_json", "isvalid_string_primitive", "isvalid_number_primitive_strict", "isvalid_bool_primitive",
54+
"isvalid_null_primitive", "invalid_json_strict", "isinvalid_string_primitive_strict",
55+
"isinvalid_number_primitive_strict", "isinvalid_bool_primitive_strict", "isinvalid_null_primitive_strict",
56+
"isinvalid_json", "isinvalid_json_strict" };
57+
58+
59+
reports:
60+
ok::
61+
"$(this.promise_filename) Pass";
62+
!ok::
63+
"$(this.promise_filename) FAIL";
64+
}

0 commit comments

Comments
 (0)