From 354d5db7347140e6610eb1b98859fbfb5cab5b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Tue, 26 Jan 2021 13:29:53 +0100 Subject: [PATCH] Fix undefined behavior on memcpy() libnetconf2's test `test_server_thread` eventually ends up in this stack trace: libyang/src/tree_schema.c:3288:16: runtime error: null pointer passed as argument 1, which is declared to never be null /nix/store/ypih4394q488ljr421x8jak55vmr0ckn-glibc-2.32-dev/include/string.h:44:28: note: nonnull attribute specified here #0 0x7f565ebf8f6e in lys_node_dup_recursion libyang/src/tree_schema.c:3288:9 #1 0x7f565ebf3409 in lys_node_dup libyang/src/tree_schema.c:3609:14 #2 0x7f565ebbf62c in yang_check_deviation libyang/src/parser_yang.c:4646:26 #3 0x7f565eba6531 in yang_check_sub_module libyang/src/parser_yang.c:4784:13 #4 0x7f565eba3d1c in yang_read_module libyang/src/parser_yang.c:2705:13 #5 0x7f565ebd1077 in lys_parse_mem_ libyang/src/tree_schema.c:1083:15 #6 0x7f565ebd31ab in lys_parse_fd_ libyang/src/tree_schema.c:1271:14 #7 0x7f565e92f291 in ly_ctx_load_localfile libyang/src/context.c:916:39 #8 0x7f565e92c31b in ly_ctx_load_sub_module libyang/src/context.c:1063:19 #9 0x7f565e92fdcc in ly_ctx_load_module libyang/src/context.c:1102:12 #10 0x597422 in main libnetconf2/tests/test_server_thread.c:686:5 #11 0x7f565dc98dbc in __libc_start_main (/nix/store/kah5n342wz4i0s9lz9ka4bgz91xa2i94-glibc-2.32/lib/libc.so.6+0x23dbc) #12 0x42a4d9 in _start /build/glibc-2.32/csu/../sysdeps/x86_64/start.S:120 In other words, it would call `memcpy` with the source parameter being NULL, which is [explicitly said to be undefined behavior](https://www.imperialviolet.org/2016/06/26/nonnull.html). --- src/tree_schema.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tree_schema.c b/src/tree_schema.c index 071bb52cd..33bec0044 100644 --- a/src/tree_schema.c +++ b/src/tree_schema.c @@ -3285,7 +3285,9 @@ lys_node_dup_recursion(struct lys_module *module, struct lys_node *parent, const } } } else { - memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature); + if (node->iffeature_size) { + memcpy(retval->iffeature, node->iffeature, retval->iffeature_size * sizeof *retval->iffeature); + } } /*