* Fixed: mandatory leaf in a uses statement caused abort
* Occurence was in ietf-yang-patch.yang
This commit is contained in:
parent
270c47b396
commit
6bb6faadc9
4 changed files with 64 additions and 31 deletions
|
|
@ -42,6 +42,8 @@ Developers may need to change their code
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
|
||||||
|
* Fixed: mandatory leaf in a uses statement caused abort
|
||||||
|
* Occurence was in ietf-yang-patch.yang
|
||||||
* Native RESTCONF fixes for http/1 or http/2 only modes
|
* Native RESTCONF fixes for http/1 or http/2 only modes
|
||||||
* Memleak in http/1-only
|
* Memleak in http/1-only
|
||||||
* Exit if http/1 request sent to http/2-only (bad client magic)
|
* Exit if http/1 request sent to http/2-only (bad client magic)
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,7 @@ char *yang_argument_get(yang_stmt *ys);
|
||||||
int yang_argument_set(yang_stmt *ys, char *arg);
|
int yang_argument_set(yang_stmt *ys, char *arg);
|
||||||
|
|
||||||
cg_var *yang_cv_get(yang_stmt *ys);
|
cg_var *yang_cv_get(yang_stmt *ys);
|
||||||
|
int yang_cv_set(yang_stmt *ys, cg_var *cv);
|
||||||
cvec *yang_cvec_get(yang_stmt *ys);
|
cvec *yang_cvec_get(yang_stmt *ys);
|
||||||
int yang_cvec_set(yang_stmt *ys, cvec *cvv);
|
int yang_cvec_set(yang_stmt *ys, cvec *cvv);
|
||||||
uint16_t yang_flag_get(yang_stmt *ys, uint16_t flag);
|
uint16_t yang_flag_get(yang_stmt *ys, uint16_t flag);
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,18 @@ yang_cv_get(yang_stmt *ys)
|
||||||
return ys->ys_cv;
|
return ys->ys_cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Set yang statement CLIgen variable
|
||||||
|
* @param[in] ys Yang statement node
|
||||||
|
* @param[in] cv cligen variable
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
yang_cv_set(yang_stmt *ys,
|
||||||
|
cg_var *cv)
|
||||||
|
{
|
||||||
|
ys->ys_cv = cv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Get yang statement CLIgen variable vector
|
/*! Get yang statement CLIgen variable vector
|
||||||
* @param[in] ys Yang statement node
|
* @param[in] ys Yang statement node
|
||||||
*/
|
*/
|
||||||
|
|
@ -456,13 +468,14 @@ int
|
||||||
ys_free1(yang_stmt *ys,
|
ys_free1(yang_stmt *ys,
|
||||||
int self)
|
int self)
|
||||||
{
|
{
|
||||||
|
cg_var *cv;
|
||||||
if (ys->ys_argument){
|
if (ys->ys_argument){
|
||||||
free(ys->ys_argument);
|
free(ys->ys_argument);
|
||||||
ys->ys_argument = NULL;
|
ys->ys_argument = NULL;
|
||||||
}
|
}
|
||||||
if (ys->ys_cv){
|
if ((cv = yang_cv_get(ys)) != NULL){
|
||||||
cv_free(ys->ys_cv);
|
cv_free(cv);
|
||||||
ys->ys_cv = NULL;
|
yang_cv_set(ys, NULL);
|
||||||
}
|
}
|
||||||
if (ys->ys_cvec){
|
if (ys->ys_cvec){
|
||||||
cvec_free(ys->ys_cvec);
|
cvec_free(ys->ys_cvec);
|
||||||
|
|
@ -601,6 +614,8 @@ ys_cp(yang_stmt *ynew,
|
||||||
int i;
|
int i;
|
||||||
yang_stmt *ycn; /* new child */
|
yang_stmt *ycn; /* new child */
|
||||||
yang_stmt *yco; /* old child */
|
yang_stmt *yco; /* old child */
|
||||||
|
cg_var *cvn;
|
||||||
|
cg_var *cvo;
|
||||||
|
|
||||||
memcpy(ynew, yold, sizeof(*yold));
|
memcpy(ynew, yold, sizeof(*yold));
|
||||||
ynew->ys_parent = NULL;
|
ynew->ys_parent = NULL;
|
||||||
|
|
@ -614,11 +629,13 @@ ys_cp(yang_stmt *ynew,
|
||||||
clicon_err(OE_YANG, errno, "strdup");
|
clicon_err(OE_YANG, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (yold->ys_cv)
|
if ((cvo = yang_cv_get(yold)) != NULL){
|
||||||
if ((ynew->ys_cv = cv_dup(yold->ys_cv)) == NULL){
|
if ((cvn = cv_dup(cvo)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cv_dup");
|
clicon_err(OE_YANG, errno, "cv_dup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
yang_cv_set(ynew, cvn);
|
||||||
|
}
|
||||||
if (yold->ys_cvec)
|
if (yold->ys_cvec)
|
||||||
if ((ynew->ys_cvec = cvec_dup(yold->ys_cvec)) == NULL){
|
if ((ynew->ys_cvec = cvec_dup(yold->ys_cvec)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cvec_dup");
|
clicon_err(OE_YANG, errno, "cvec_dup");
|
||||||
|
|
@ -1770,8 +1787,7 @@ ys_populate_leaf(clicon_handle h,
|
||||||
|
|
||||||
yparent = ys->ys_parent; /* Find parent: list/container */
|
yparent = ys->ys_parent; /* Find parent: list/container */
|
||||||
/* 1. Find type specification and set cv type accordingly */
|
/* 1. Find type specification and set cv type accordingly */
|
||||||
if (yang_type_get(ys, &origtype, &yrestype, &options, NULL, NULL, NULL, &fraction_digits)
|
if (yang_type_get(ys, &origtype, &yrestype, &options, NULL, NULL, NULL, &fraction_digits) < 0)
|
||||||
< 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
restype = yrestype?yrestype->ys_argument:NULL;
|
restype = yrestype?yrestype->ys_argument:NULL;
|
||||||
if (clicon_type2cv(origtype, restype, ys, &cvtype) < 0) /* This handles non-resolved also */
|
if (clicon_type2cv(origtype, restype, ys, &cvtype) < 0) /* This handles non-resolved also */
|
||||||
|
|
@ -1828,7 +1844,7 @@ ys_populate_leaf(clicon_handle h,
|
||||||
if ((ret = yang_key_match(yparent, ys->ys_argument)) < 0)
|
if ((ret = yang_key_match(yparent, ys->ys_argument)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
ys->ys_cv = cv;
|
yang_cv_set(ys, cv);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (origtype)
|
if (origtype)
|
||||||
|
|
@ -2241,7 +2257,7 @@ ys_populate_feature(clicon_handle h,
|
||||||
cv_bool_set(cv, found);
|
cv_bool_set(cv, found);
|
||||||
if (found)
|
if (found)
|
||||||
clicon_debug(1, "%s %s:%s", __FUNCTION__, module, feature);
|
clicon_debug(1, "%s %s:%s", __FUNCTION__, module, feature);
|
||||||
ys->ys_cv = cv;
|
yang_cv_set(ys, cv);
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -2495,7 +2511,7 @@ yang_if_feature(clicon_handle h,
|
||||||
yang_stmt *yfeat; /* feature yang node */
|
yang_stmt *yfeat; /* feature yang node */
|
||||||
int opand = -1; /* -1:not set, 0:or, 1:and */
|
int opand = -1; /* -1:not set, 0:or, 1:and */
|
||||||
int enabled = 0;
|
int enabled = 0;
|
||||||
|
cg_var *cv;
|
||||||
if ((vec = clicon_strsep(ys->ys_argument, " \t\r\n", &nvec)) == NULL)
|
if ((vec = clicon_strsep(ys->ys_argument, " \t\r\n", &nvec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Two steps: first detect operators
|
/* Two steps: first detect operators
|
||||||
|
|
@ -2584,7 +2600,8 @@ yang_if_feature(clicon_handle h,
|
||||||
/* Check if this feature is enabled or not
|
/* Check if this feature is enabled or not
|
||||||
* Continue loop to catch unbound features and make verdict at end
|
* Continue loop to catch unbound features and make verdict at end
|
||||||
*/
|
*/
|
||||||
if (yfeat->ys_cv == NULL || !cv_bool_get(yfeat->ys_cv)){ /* disabled */
|
cv = yang_cv_get(yfeat);
|
||||||
|
if (cv == NULL || !cv_bool_get(cv)){ /* disabled */
|
||||||
/* if AND then this is permanently disabled */
|
/* if AND then this is permanently disabled */
|
||||||
if (opand && enabled)
|
if (opand && enabled)
|
||||||
enabled = 0;
|
enabled = 0;
|
||||||
|
|
@ -3024,14 +3041,15 @@ int
|
||||||
yang_mandatory(yang_stmt *ys)
|
yang_mandatory(yang_stmt *ys)
|
||||||
{
|
{
|
||||||
yang_stmt *ym;
|
yang_stmt *ym;
|
||||||
|
cg_var *cv;
|
||||||
|
|
||||||
/* 1) A leaf, choice, anydata, or anyxml node with a "mandatory"
|
/* 1) A leaf, choice, anydata, or anyxml node with a "mandatory"
|
||||||
* statement with the value "true". */
|
* statement with the value "true". */
|
||||||
if (ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_CHOICE ||
|
if (ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_CHOICE ||
|
||||||
ys->ys_keyword == Y_ANYDATA || ys->ys_keyword == Y_ANYXML){
|
ys->ys_keyword == Y_ANYDATA || ys->ys_keyword == Y_ANYXML){
|
||||||
if ((ym = yang_find(ys, Y_MANDATORY, NULL)) != NULL){
|
if ((ym = yang_find(ys, Y_MANDATORY, NULL)) != NULL){
|
||||||
if (ym->ys_cv != NULL) /* shouldnt happen */
|
if ((cv = yang_cv_get(ym)) != NULL) /* shouldnt happen */
|
||||||
return cv_bool_get(ym->ys_cv);
|
return cv_bool_get(cv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0 /* See note above */
|
#if 0 /* See note above */
|
||||||
|
|
@ -3071,9 +3089,9 @@ yang_config(yang_stmt *ys)
|
||||||
yang_stmt *ym;
|
yang_stmt *ym;
|
||||||
|
|
||||||
if ((ym = yang_find(ys, Y_CONFIG, NULL)) != NULL){
|
if ((ym = yang_find(ys, Y_CONFIG, NULL)) != NULL){
|
||||||
if (ym->ys_cv == NULL) /* shouldnt happen */
|
if (yang_cv_get(ym) == NULL) /* shouldnt happen */
|
||||||
return 1;
|
return 1;
|
||||||
return cv_bool_get(ym->ys_cv);
|
return cv_bool_get(yang_cv_get(ym));
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1767,29 +1767,33 @@ cg_var *
|
||||||
ys_parse(yang_stmt *ys,
|
ys_parse(yang_stmt *ys,
|
||||||
enum cv_type cvtype)
|
enum cv_type cvtype)
|
||||||
{
|
{
|
||||||
int cvret;
|
int cvret;
|
||||||
char *reason = NULL;
|
char *reason = NULL;
|
||||||
|
cg_var *cv = NULL;
|
||||||
|
|
||||||
assert(yang_cv_get(ys) == NULL); /* Cv:s are parsed in different places, difficult to separate */
|
if ((cv = yang_cv_get(ys)) != NULL){
|
||||||
if ((ys->ys_cv = cv_new(cvtype)) == NULL){
|
/* eg mandatory in uses is already set and then copied */
|
||||||
|
cv_free(cv);
|
||||||
|
yang_cv_set(ys, NULL);
|
||||||
|
}
|
||||||
|
if ((cv = cv_new(cvtype)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cv_new");
|
clicon_err(OE_YANG, errno, "cv_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((cvret = cv_parse1(yang_argument_get(ys), ys->ys_cv, &reason)) < 0){ /* error */
|
if ((cvret = cv_parse1(yang_argument_get(ys), cv, &reason)) < 0){ /* error */
|
||||||
clicon_err(OE_YANG, errno, "parsing cv");
|
clicon_err(OE_YANG, errno, "parsing cv");
|
||||||
ys->ys_cv = NULL;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (cvret == 0){ /* parsing failed */
|
if (cvret == 0){ /* parsing failed */
|
||||||
clicon_err(OE_YANG, errno, "Parsing CV: %s", reason);
|
clicon_err(OE_YANG, errno, "Parsing CV: %s", reason);
|
||||||
ys->ys_cv = NULL;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
yang_cv_set(ys, cv);
|
||||||
/* cvret == 1 means parsing is OK */
|
/* cvret == 1 means parsing is OK */
|
||||||
done:
|
done:
|
||||||
if (reason)
|
if (reason)
|
||||||
free(reason);
|
free(reason);
|
||||||
return ys->ys_cv;
|
return yang_cv_get(ys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! First round yang syntactic statement specific checks. No context checks.
|
/*! First round yang syntactic statement specific checks. No context checks.
|
||||||
|
|
@ -1819,6 +1823,7 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
char *reason = NULL;
|
char *reason = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t minmax;
|
uint32_t minmax;
|
||||||
|
cg_var *cv = NULL;
|
||||||
|
|
||||||
arg = yang_argument_get(ys);
|
arg = yang_argument_get(ys);
|
||||||
keyword = yang_keyword_get(ys);
|
keyword = yang_keyword_get(ys);
|
||||||
|
|
@ -1826,7 +1831,11 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
case Y_FRACTION_DIGITS:
|
case Y_FRACTION_DIGITS:
|
||||||
if (ys_parse(ys, CGV_UINT8) == NULL)
|
if (ys_parse(ys, CGV_UINT8) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
fd = cv_uint8_get(ys->ys_cv);
|
if ((cv = yang_cv_get(ys)) == NULL){
|
||||||
|
clicon_err(OE_YANG, ENOENT, "Unexpected NULL cv");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
fd = cv_uint8_get(cv);
|
||||||
if (fd < 1 || fd > 18){
|
if (fd < 1 || fd > 18){
|
||||||
clicon_err(OE_YANG, errno, "%u: Out of range, should be [1:18]", fd);
|
clicon_err(OE_YANG, errno, "%u: Out of range, should be [1:18]", fd);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1841,11 +1850,12 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
case Y_REVISION_DATE: /* YYYY-MM-DD encoded as uint32 YYYYMMDD */
|
case Y_REVISION_DATE: /* YYYY-MM-DD encoded as uint32 YYYYMMDD */
|
||||||
if (ys_parse_date_arg(arg, &date) < 0)
|
if (ys_parse_date_arg(arg, &date) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((ys->ys_cv = cv_new(CGV_UINT32)) == NULL){
|
if ((cv = cv_new(CGV_UINT32)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cv_new");
|
clicon_err(OE_YANG, errno, "cv_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cv_uint32_set(ys->ys_cv, date);
|
yang_cv_set(ys, cv);
|
||||||
|
cv_uint32_set(cv, date);
|
||||||
break;
|
break;
|
||||||
case Y_STATUS: /* RFC7950 7.21.2: "current", "deprecated", or "obsolete". */
|
case Y_STATUS: /* RFC7950 7.21.2: "current", "deprecated", or "obsolete". */
|
||||||
if (strcmp(arg, "current") &&
|
if (strcmp(arg, "current") &&
|
||||||
|
|
@ -1858,13 +1868,14 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
break;
|
break;
|
||||||
case Y_MAX_ELEMENTS:
|
case Y_MAX_ELEMENTS:
|
||||||
case Y_MIN_ELEMENTS:
|
case Y_MIN_ELEMENTS:
|
||||||
if ((ys->ys_cv = cv_new(CGV_UINT32)) == NULL){
|
if ((cv = cv_new(CGV_UINT32)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cv_new");
|
clicon_err(OE_YANG, errno, "cv_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
yang_cv_set(ys, cv);
|
||||||
if (keyword == Y_MAX_ELEMENTS &&
|
if (keyword == Y_MAX_ELEMENTS &&
|
||||||
strcmp(arg, "unbounded") == 0)
|
strcmp(arg, "unbounded") == 0)
|
||||||
cv_uint32_set(ys->ys_cv, 0); /* 0 means unbounded for max */
|
cv_uint32_set(cv, 0); /* 0 means unbounded for max */
|
||||||
else{
|
else{
|
||||||
if ((ret = parse_uint32(arg, &minmax, &reason)) < 0){
|
if ((ret = parse_uint32(arg, &minmax, &reason)) < 0){
|
||||||
clicon_err(OE_YANG, errno, "parse_uint32");
|
clicon_err(OE_YANG, errno, "parse_uint32");
|
||||||
|
|
@ -1876,7 +1887,7 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
free(reason);
|
free(reason);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cv_uint32_set(ys->ys_cv, minmax);
|
cv_uint32_set(cv, minmax);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Y_MODIFIER:
|
case Y_MODIFIER:
|
||||||
|
|
@ -1888,11 +1899,12 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
case Y_UNKNOWN:{ /* save (optional) argument in ys_cv */
|
case Y_UNKNOWN:{ /* save (optional) argument in ys_cv */
|
||||||
if (extra == NULL)
|
if (extra == NULL)
|
||||||
break;
|
break;
|
||||||
if ((ys->ys_cv = cv_new(CGV_STRING)) == NULL){
|
if ((cv = cv_new(CGV_STRING)) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cv_new");
|
clicon_err(OE_YANG, errno, "cv_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((ret = cv_parse1(extra, ys->ys_cv, &reason)) < 0){ /* error */
|
yang_cv_set(ys, cv);
|
||||||
|
if ((ret = cv_parse1(extra, cv, &reason)) < 0){ /* error */
|
||||||
clicon_err(OE_YANG, errno, "parsing cv");
|
clicon_err(OE_YANG, errno, "parsing cv");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue