@@ -810,6 +810,49 @@ lys_compile_unres_disabled_bitenum(struct lysc_ctx *ctx, struct lysc_node_leaf *
810810 return LY_SUCCESS ;
811811}
812812
813+ /**
814+ * @brief Check a leafref for circular references.
815+ *
816+ * @param[in] type Referenced type, is checked recursively for other leafrefs.
817+ * @param[in] lref Initial leafref type that cannot be referenced.
818+ * @return LY_SUCCESS on success;
819+ * @return LY_EVALID on a circular chein of leafrefs.
820+ */
821+ static LY_ERR
822+ lys_compile_leafref_circ_check (const struct lysc_type * type , const struct lysc_type * lref )
823+ {
824+ const struct lysc_type_union * un ;
825+ LY_ARRAY_COUNT_TYPE u ;
826+
827+ if (!type ) {
828+ /* not resolved yet */
829+ return LY_SUCCESS ;
830+ }
831+
832+ if (type == lref ) {
833+ /* circular chain detected */
834+ return LY_EVALID ;
835+ }
836+
837+ switch (type -> basetype ) {
838+ case LY_TYPE_LEAFREF :
839+ /* check the referenced type */
840+ LY_CHECK_RET (lys_compile_leafref_circ_check (((struct lysc_type_leafref * )type )-> realtype , lref ));
841+ break ;
842+ case LY_TYPE_UNION :
843+ /* check all the union types */
844+ un = (struct lysc_type_union * )type ;
845+ LY_ARRAY_FOR (un -> types , u ) {
846+ LY_CHECK_RET (lys_compile_leafref_circ_check (un -> types [u ], lref ));
847+ }
848+ default :
849+ /* no more leafref references */
850+ break ;
851+ }
852+
853+ return LY_SUCCESS ;
854+ }
855+
813856/**
814857 * @brief Check leafref for its target existence on a complete compiled schema tree.
815858 *
@@ -825,7 +868,6 @@ lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, st
825868{
826869 const struct lysc_node * target = NULL ;
827870 struct ly_path * p ;
828- struct lysc_type * type ;
829871 uint16_t flg ;
830872
831873 assert (node -> nodetype & (LYS_LEAF | LYS_LEAFLIST ));
@@ -881,17 +923,12 @@ lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, st
881923 }
882924
883925 /* check for circular chain of leafrefs */
884- for (type = ((struct lysc_node_leaf * )target )-> type ;
885- type && (type -> basetype == LY_TYPE_LEAFREF );
886- type = ((struct lysc_type_leafref * )type )-> realtype ) {
887- if (type == (struct lysc_type * )lref ) {
888- /* circular chain detected */
889- LOG_LOCSET (node );
890- LOGVAL (ctx -> ctx , NULL , LYVE_REFERENCE , "Invalid leafref path \"%s\" - circular chain of leafrefs detected." ,
891- lref -> path -> expr );
892- LOG_LOCBACK (1 );
893- return LY_EVALID ;
894- }
926+ if (lys_compile_leafref_circ_check (((struct lysc_node_leaf * )target )-> type , (struct lysc_type * )lref )) {
927+ LOG_LOCSET (node );
928+ LOGVAL (ctx -> ctx , NULL , LYVE_REFERENCE , "Invalid leafref path \"%s\" - circular chain of leafrefs detected." ,
929+ lref -> path -> expr );
930+ LOG_LOCBACK (1 );
931+ return LY_EVALID ;
895932 }
896933
897934 /* store the type */
0 commit comments