diff options
-rw-r--r-- | libfdt/fdt_ro.c | 63 | ||||
-rw-r--r-- | libfdt/libfdt.h | 2 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/Makefile.tests | 2 | ||||
-rw-r--r-- | tests/check_full.c | 63 | ||||
-rw-r--r-- | tests/dumptrees.c | 2 | ||||
-rwxr-xr-x | tests/run_tests.sh | 9 |
7 files changed, 141 insertions, 1 deletions
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index c74b962..4ba7c93 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -857,3 +857,66 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, return offset; /* error from fdt_next_node() */ } + +int fdt_check_full(const void *fdt, size_t bufsize) +{ + int err; + int num_memrsv; + int offset, nextoffset = 0; + uint32_t tag; + unsigned depth = 0; + const void *prop; + const char *propname; + + if (bufsize < FDT_V1_SIZE) + return -FDT_ERR_TRUNCATED; + err = fdt_check_header(fdt); + if (err != 0) + return err; + if (bufsize < fdt_totalsize(fdt)) + return -FDT_ERR_TRUNCATED; + + num_memrsv = fdt_num_mem_rsv(fdt); + if (num_memrsv < 0) + return num_memrsv; + + while (1) { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + if (nextoffset < 0) + return nextoffset; + + switch (tag) { + case FDT_NOP: + break; + + case FDT_END: + if (depth != 0) + return -FDT_ERR_BADSTRUCTURE; + return 0; + + case FDT_BEGIN_NODE: + depth++; + if (depth > INT_MAX) + return -FDT_ERR_BADSTRUCTURE; + break; + + case FDT_END_NODE: + if (depth == 0) + return -FDT_ERR_BADSTRUCTURE; + depth--; + break; + + case FDT_PROP: + prop = fdt_getprop_by_offset(fdt, offset, &propname, + &err); + if (!prop) + return err; + break; + + default: + return -FDT_ERR_INTERNAL; + } + } +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 9938fb8..f044298 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -295,6 +295,8 @@ int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ /**********************************************************************/ +int fdt_check_full(const void *fdt, size_t bufsize); + /** * fdt_get_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob diff --git a/tests/.gitignore b/tests/.gitignore index ea437ca..d423570 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -8,6 +8,7 @@ tmp.* /asm_tree_dump /boot-cpuid /char_literal +/check_full /check_header /check_path /del_node diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 489886f..2c2c4fd 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -26,7 +26,7 @@ LIB_TESTS_L = get_mem_rsv \ property_iterate \ subnode_iterate \ overlay overlay_bad_fixup \ - check_path check_header + check_path check_header check_full LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv diff --git a/tests/check_full.c b/tests/check_full.c new file mode 100644 index 0000000..04c0bc1 --- /dev/null +++ b/tests/check_full.c @@ -0,0 +1,63 @@ +/* + * libfdt - Flat Device Tree manipulation + * Tests if two given dtbs are structurally equal (including order) + * Copyright (C) 2007 David Gibson, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#include <libfdt.h> + +#include "tests.h" +#include "testdata.h" + +static int expect_bad; /* = 0 */ + +int main(int argc, char *argv[]) +{ + const char *filename; + char *fdt; + size_t len; + int err; + + test_init(argc, argv); + if ((argc != 2) + && ((argc != 3) || !streq(argv[1], "-n"))) + CONFIG("Usage: %s [-n] <dtb file>", argv[0]); + if (argc == 3) + expect_bad = 1; + + filename = argv[argc-1]; + err = utilfdt_read_err(filename, &fdt, &len); + if (err) + CONFIG("Couldn't open blob from \"%s\": %s", + filename, strerror(err)); + + vg_prepare_blob(fdt, len); + + err = fdt_check_full(fdt, len); + + if (expect_bad && (err == 0)) + FAIL("fdt_check_full() succeeded unexpectedly"); + else if (!expect_bad && (err != 0)) + FAIL("fdt_check_full() failed: %s", fdt_strerror(err)); + + PASS(); +} diff --git a/tests/dumptrees.c b/tests/dumptrees.c index 87d1c3d..ff5818d 100644 --- a/tests/dumptrees.c +++ b/tests/dumptrees.c @@ -37,6 +37,8 @@ static struct { TREE(test_tree1), TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char), TREE(ovf_size_strings), + TREE(truncated_property), TREE(truncated_string), + TREE(truncated_memrsv), }; #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f80029a..2215e8a 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -445,6 +445,15 @@ libfdt_tests () { run_wrap_error_test $DTC -I dtb -O dts -o /dev/null ovf_size_strings.dtb run_test check_header test_tree1.dtb + + # check full tests + for good in test_tree1.dtb; do + run_test check_full $good + done + for bad in truncated_property.dtb truncated_string.dtb \ + truncated_memrsv.dtb; do + run_test check_full -n $bad + done } dtc_tests () { |