@@ -150,6 +150,50 @@ lyb_parse_union(const void *lyb_data, size_t lyb_data_len, uint32_t *type_idx, c
150150 }
151151}
152152
153+ /**
154+ * @brief For leafref failures, ensure the appropriate error is propagated, not a type validation failure.
155+ *
156+ * RFC7950 Section 15.5 defines the appropriate error app tag of "require-instance".
157+ *
158+ * @param[in,out] err Error record to be updated
159+ * @param[in] type leafref type used to extract target path
160+ * @param[in] value value attempting to be stored
161+ * @param[in] value_len Length of value that was attempted to be stored.
162+ * @return LY_ERR value. Only possible errors are LY_SUCCESS and LY_EMEM.
163+ */
164+ static LY_ERR
165+ union_update_lref_err (struct ly_err_item * err , const struct lysc_type * type , const void * value , size_t value_len )
166+ {
167+ const struct lysc_type_leafref * lref ;
168+ char * valstr = NULL ;
169+ int msg_len ;
170+
171+ if ((err == NULL ) || (type -> basetype != LY_TYPE_LEAFREF )) {
172+ return LY_SUCCESS ;
173+ }
174+
175+ lref = (const struct lysc_type_leafref * )type ;
176+ free (err -> apptag );
177+ err -> apptag = strdup ("instance-required" );
178+ if (err -> apptag == NULL ) {
179+ return LY_EMEM ;
180+ }
181+
182+ free (err -> msg );
183+ err -> msg = NULL ;
184+ valstr = strndup ((const char * )value , value_len );
185+ if (valstr == NULL ) {
186+ return LY_EMEM ;
187+ }
188+
189+ msg_len = asprintf (& err -> msg , LY_ERRMSG_NOLREF_VAL , valstr , lyxp_get_expr (lref -> path ));
190+ free (valstr );
191+ if (msg_len == -1 ) {
192+ return LY_EMEM ;
193+ }
194+ return LY_SUCCESS ;
195+ }
196+
153197/**
154198 * @brief Store (and validate) subvalue as a specific type.
155199 *
@@ -170,7 +214,7 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3
170214 uint32_t options , ly_bool validate , const struct lyd_node * ctx_node , const struct lyd_node * tree ,
171215 struct lys_glob_unres * unres , struct ly_err_item * * err )
172216{
173- LY_ERR rc = LY_SUCCESS ;
217+ LY_ERR urc , rc = LY_SUCCESS ;
174218 struct lysc_type * type = type_u -> types [type_idx ];
175219 const void * value = NULL ;
176220 size_t value_len = 0 ;
@@ -190,7 +234,13 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3
190234 if ((rc != LY_SUCCESS ) && (rc != LY_EINCOMPLETE )) {
191235 /* clear any leftover/freed garbage */
192236 memset (& subvalue -> value , 0 , sizeof subvalue -> value );
193- return rc ;
237+
238+ /* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
239+ urc = union_update_lref_err (* err , type_u -> types [ti ], value , value_len );
240+ if (urc != LY_SUCCESS ) {
241+ rc = urc ;
242+ }
243+ goto cleanup ;
194244 }
195245
196246 assert (subvalue -> value .realtype );
@@ -219,16 +269,19 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3
219269 if (options & LYPLG_TYPE_STORE_ONLY ) {
220270 opts |= LYPLG_TYPE_STORE_ONLY ;
221271 }
222- if (dynamic ) {
223- opts |= LYPLG_TYPE_STORE_DYNAMIC ;
224- }
225272
226273 rc = type -> plugin -> store (ctx , type , value , value_len , opts , format , prefix_data , subvalue -> hints ,
227274 subvalue -> ctx_node , & subvalue -> value , unres , err );
228275 if ((rc != LY_SUCCESS ) && (rc != LY_EINCOMPLETE )) {
229276 /* clear any leftover/freed garbage */
230277 memset (& subvalue -> value , 0 , sizeof subvalue -> value );
231- return rc ;
278+
279+ /* if this is a leafref, lets make sure we propagate the appropriate error, and not a type validation failure */
280+ urc = union_update_lref_err (* err , type , value , value_len );
281+ if (urc != LY_SUCCESS ) {
282+ rc = urc ;
283+ }
284+ goto cleanup ;
232285 }
233286
234287 if (validate && (rc == LY_EINCOMPLETE )) {
@@ -240,6 +293,10 @@ union_store_type(const struct ly_ctx *ctx, struct lysc_type_union *type_u, uint3
240293 }
241294 }
242295
296+ cleanup :
297+ if (dynamic ) {
298+ free ((void * )value );
299+ }
243300 return rc ;
244301}
245302
0 commit comments