Skip to content

Commit 0706f8d

Browse files
committed
context UPDATE module order matters for hash
Because it matters for LYB data where the absolute index of a module is stored to identify it. Refs #2443
1 parent e46200e commit 0706f8d

File tree

4 files changed

+34
-60
lines changed

4 files changed

+34
-60
lines changed

src/context.c

Lines changed: 11 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -751,77 +751,38 @@ ly_ctx_get_modules_hash(const struct ly_ctx *ctx)
751751
return ctx->mod_hash;
752752
}
753753

754-
/**
755-
* @brief qsort() alphabetical compare of modules.
756-
*/
757-
static int
758-
ly_ctx_mod_cmp_cb(const void *ptr1, const void *ptr2)
759-
{
760-
const struct lys_module *mod1, *mod2;
761-
int r;
762-
763-
mod1 = *(struct lys_module **)ptr1;
764-
mod2 = *(struct lys_module **)ptr2;
765-
766-
/* module name */
767-
r = strcmp(mod1->name, mod2->name);
768-
if (!r) {
769-
/* revision */
770-
if (mod1->revision && !mod2->revision) {
771-
r = 1;
772-
} else if (!mod1->revision && mod2->revision) {
773-
r = -1;
774-
} else if (mod1->revision && mod2->revision) {
775-
r = strcmp(mod1->revision, mod2->revision);
776-
}
777-
}
778-
779-
return r;
780-
}
781-
782754
void
783755
ly_ctx_new_change(struct ly_ctx *ctx)
784756
{
785-
uint32_t i, hash = 0;
786-
const struct lys_module **mods = NULL;
757+
const struct lys_module *mod;
758+
uint32_t i = ly_ctx_internal_modules_count(ctx), hash = 0;
787759
LY_ARRAY_COUNT_TYPE u;
788760

789761
/* change counter */
790762
ctx->change_count++;
791763

792-
/* collect modules into an array */
793-
mods = malloc(ctx->modules.count * sizeof *mods);
794-
LY_CHECK_ERR_GOTO(!mods, LOGMEM(ctx), cleanup);
795-
memcpy(mods, ctx->modules.objs, ctx->modules.count * sizeof *mods);
796-
797-
/* sort modules alphabetically */
798-
qsort(mods, ctx->modules.count, sizeof *mods, ly_ctx_mod_cmp_cb);
799-
800-
/* calculate module hash */
801-
for (i = 0; i < ctx->modules.count; ++i) {
764+
/* module hash */
765+
while ((mod = ly_ctx_get_module_iter(ctx, &i))) {
802766
/* name */
803-
hash = lyht_hash_multi(hash, mods[i]->name, strlen(mods[i]->name));
767+
hash = lyht_hash_multi(hash, mod->name, strlen(mod->name));
804768

805769
/* revision */
806-
if (mods[i]->revision) {
807-
hash = lyht_hash_multi(hash, mods[i]->revision, strlen(mods[i]->revision));
770+
if (mod->revision) {
771+
hash = lyht_hash_multi(hash, mod->revision, strlen(mod->revision));
808772
}
809773

810774
/* enabled features */
811-
if (mods[i]->implemented) {
812-
LY_ARRAY_FOR(mods[i]->compiled->features, u) {
813-
hash = lyht_hash_multi(hash, mods[i]->compiled->features[u], strlen(mods[i]->compiled->features[u]));
775+
if (mod->implemented) {
776+
LY_ARRAY_FOR(mod->compiled->features, u) {
777+
hash = lyht_hash_multi(hash, mod->compiled->features[u], strlen(mod->compiled->features[u]));
814778
}
815779
}
816780

817781
/* imported/implemented */
818-
hash = lyht_hash_multi(hash, (char *)&mods[i]->implemented, sizeof mods[i]->implemented);
782+
hash = lyht_hash_multi(hash, (char *)&mod->implemented, sizeof mod->implemented);
819783
}
820784

821785
ctx->mod_hash = lyht_hash_multi(hash, NULL, 0);
822-
823-
cleanup:
824-
free(mods);
825786
}
826787

827788
LIBYANG_API_DEF ly_module_imp_clb

src/context.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,10 +414,14 @@ LIBYANG_API_DECL LY_ERR ly_ctx_unset_options(struct ly_ctx *ctx, uint32_t option
414414
LIBYANG_API_DECL uint16_t ly_ctx_get_change_count(const struct ly_ctx *ctx);
415415

416416
/**
417-
* @brief Get the hash of all the modules in the context.
417+
* @brief Get the hash of all the modules in the context. Since order of the modules is significant,
418+
* even when 2 contexts have the same modules but loaded in a different order, the hash will differ.
419+
*
420+
* Modules are added into the context in the order they are loaded in, imports following the modules
421+
* that imported them.
418422
*
419423
* Hash consists of all module names (1), their revisions (2), all enabled features (3), and their
420-
* imported/implemented state (4). Context module order is not significant.
424+
* imported/implemented state (4).
421425
*
422426
* @param[in] ctx Context to be examined.
423427
* @return Context modules hash.

src/parser_data.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,16 @@ struct ly_in;
156156
for that is that the data may be parsed incorrectly possibly
157157
leading to a crash. However, this hash restriction is too severe
158158
and the hash must match only with regard to the modules with actual
159-
YANG data in the LYB data to guarantee correct data parsing. In other
160-
words, if there is a module A in the printing context but no data
161-
of this module in the LYB data, the parsing context does not have
162-
to have module A loaded but the hash check will fail in that case.
159+
YANG data in the LYB data and their equal absolute order in the
160+
context to guarantee correct data parsing. In other words, if there
161+
is a module A in the printing context but no data
162+
of this module in the LYB data and any YANG data belong to modules
163+
before the module A, the parsing context does not have
164+
to have module A loaded but the hash check will fail without it.
163165
So, if you are able to guarantee that the parsing context will
164-
have all the required YANG modules in the same state as in the
165-
printed context you can use this flag to effectively soften the
166-
context restriction. */
166+
have all the required YANG modules in the same state and absolute
167+
order as in the printed context you can use this flag to
168+
effectively soften the context restriction. */
167169
#define LYD_PARSE_ORDERED 0x200000 /**< Do not search for the correct place of each node but instead expect
168170
that the nodes are being parsed in the correct schema-based order,
169171
which is always true if the data were printed by libyang and not

src/parser_lyb.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,15 @@ lyb_parse_module_idx(struct lylyb_parse_ctx *lybctx, const struct lys_module **m
408408
/* read module index */
409409
lyb_read_count(&idx, lybctx);
410410

411+
/* check the read index */
412+
if (idx >= lybctx->ctx->modules.count) {
413+
LOGERR(lybctx->ctx, LY_EINT, "Invalid context for LYB data parsing, module with index %" PRIu32 " not found.",
414+
idx);
415+
rc = LY_EINT;
416+
goto cleanup;
417+
}
418+
411419
/* get the module */
412-
assert(idx < lybctx->ctx->modules.count);
413420
m = lybctx->ctx->modules.objs[idx];
414421
if (!m->implemented) {
415422
LOGERR(lybctx->ctx, LY_EINT, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",

0 commit comments

Comments
 (0)