Repository navigation
Conversation
michalvasko
left a comment
There was a problem hiding this comment.
Thanks, but will require some changes. I appreciate the tests and those will be merged but the new code is too complex and unreadable. Ideally, remove the old_mem value completely and I think you can simply define two macros instead of one macro and two functions.
d7a0cd9 to
5605762
Compare
|
Thanks for the review. I replaced the two functions and the macro with two macros: I kept |
michalvasko
left a comment
There was a problem hiding this comment.
What I meant is that you do not have to check whether the array start has actually changed but always overwrite it. It is not like every statement has hundreds of extensions, makes no difference but not needing the old_mem variable.
|
The macros do not check whether the array moved, they always overwrite. The All three instances are in To overwrite without the old address, the macro would have to know which member each substatement points to, so a switch on |
|
Okay, then you can pass the substatement (member) into the macro. With some macro magic a single macro may even support both variants, an array item member or the item itself. |
Extension instances store a pointer to their parent statement, which may be an item of a sized array, a member of such an item (flags, an embedded type or default) or a separate sized array (if-features, bases). Adding an item to such an array may move it, so the parents went stale in the YIN parser, which never updated them. The YANG parser reset the parents of statement array items to the item itself, losing the member parents, and left the parents into separate arrays stale. Add two macros setting the parent of the extension instances of a substatement, to a separate array or to every item of an array or its member, and use them wherever an array with extension instance parents grows.
fraction-digits, require-instance, value and position stored their parent's extension instance array for resolving while the parent could still add more extension instances to it. Those arrays are stored once the parent statement is parsed, the same as in the YANG parser.
The YIN parser created the extension instances of an if-feature, unique or a default of a leaf-list, refine or deviate always with the index 0, so the printers and lysp_ext_instance_path() took them all for instances of the first item. The parent of those of a default was also the item instead of the array. Set the array as the parent and the index of the item, as the YANG parser does.
5605762 to
5e3b61b
Compare
|
Done, LYSP_ARRAY_EXT_PARENTS_UPDATE(*enums, exts, enum_kw);
LYSP_ARRAY_EXT_PARENTS_UPDATE(*enums, exts, LY_STMT_VALUE);
LYSP_ARRAY_EXT_PARENTS_UPDATE(*enums, exts, LY_STMT_POSITION);
LYSP_ARRAY_EXT_PARENTS_UPDATE(*enums, exts, LY_STMT_STATUS, flags);The YIN lists also have Always setting the array as the parent needed one more fix in the YIN parser, in its own commit: it created the extension instances of an I checked the parent of every extension instance of a module with several items in each of these arrays and extension instances in all their substatements, in both formats: in YANG they are the same as with the previous version, in YIN they differ only in those indexes and |
Every
struct lysp_ext_instancekeeps aparentpointer to the statement it belongs to. That statement is often an item of a sized array (a typedef, enum, must, revision, import, ...), a member of such an item (&enum->flagsforstatus,&tpdf->dfltfordefault), or the base of a separate array withparent_stmt_index(iffeatures,bases). WhenLYA_ADD_ITEM()grows the array andrealloc()moves it, every such parent points into the freed memory.parser_yin.cnever updated these parents after adding an item, so they went stale whenever the array moved, and were later read through them (e.g. bylysp_ext_instance_path()).parser_yang.cupdated statement array items with a loop after each add, but reset every parent to the item itself, losing the member offsets of substatement parents (status,default, ...); parents into separate arrays such asiffeatureswere not updated at all.lysp_inject_submodule()grows the main module'sincludeswithout updating them either.The fix adds two macros:
LYSP_ARRAY_EXT_PARENTS_UPDATE(ARRAY, EXTS, STMT[, MEMBER])sets the parent of the extension instances of the substatementSTMTof every item of an array to the item itself or to itsMEMBER(such asflags), andLYSP_EXT_PARENTS_UPDATE(EXTS, STMT, PARENT)does it for one array of extension instances, for the separate arrays (if-feature,base,default,unique). They are used at every place an array with extension instance parents grows, in both parsers and inlysp_inject_submodule(), each listing the substatements whose parents point into the array, and replace the per-site loops inparser_yang.c.The second commit fixes another reference into a growing array in the YIN parser.
yin_parse_fracdigits(),yin_pasrse_reqinstance()andyin_parse_value_pos()stored their parent's extension instance array (type->exts,enm->exts) inctx->ext_instwhile the parenttype,enumorbitcould still add more extension instances to it. A later extension instance of the parent could move the array, andlysp_resolve_ext_instance_records()then read the freed memory. The parent statements already store their array once they are parsed, as in the YANG parser, so these three calls are removed; every remaining call stores the array of the statement that was just parsed.The third commit makes the YIN parser give the extension instances of an
if-feature,uniqueor thedefaultof a leaf-list, refine or deviate the array as their parent and the index of the item, as the YANG parser does. It created them always with the index 0 (and for adefaultwith the item as the parent), so the printers andlysp_ext_instance_path()took them all for instances of the first item.Tests:
test_ext_parent_array_reallocintests/utests/schema/test_schema.cparses the same module in YANG and YIN with three typedefs (withdefault), enums (withstatus), musts, if-features and leaf-list defaults, each with extension instances, and checks every parent points to its own statement, member or array, with the index of itsif-featureordefault.tests/utests/basic/test_plugins.cloads the extension plugin test module in YIN too and adds musts to it; the parse callback now checks that the instance is the one stored in its parent, for enums, union types, musts, typedefs and refines in both formats.test_yin_parse_type_substmt_extsintests/utests/schema/test_yin.cparsesfraction-digits,require-instance,valueandpositionwith an extension instance, each followed by more extension instances of its parent, and checks all of them are kept in order.The full test suite passes (ASan/UBSan build).