If none of the markers bears type information we can't just prepend a new one. Otherwise two subsequent markers will begin at offset 0, blowing up the chunk_len calculation a few lines after. A particular case where this causes havoc is a string property in a tree generated from "fs" input. A string property ends up with a TYPE_NULL marker. Upon output, in write_propval(), we correctly guess it looks like a TYPE_STRING. With the dummy marker prepended, We'd and up with two markers: { type = TYPE_STRING, offset = 0 } { type = TYPE_NONE, offset = 0 } The chunk_len for the fist marker will end up being calculated as 0. This blows up later on because a zero-length string should never happen because it lacks the terminating \0 (valgrind catches this). I'm also adding an assertion to write_propval_string() so that such cases won't go unnoticed in future and a test case. Signed-off-by: Lubomir Rintel <lkundrak@xxxxx> --- Changes since v1: - Oops, forgot to git add tests/fs_tree1.dts. Added now. tests/fs_tree1.dts | 43 +++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 14 ++++++++++++++ treesource.c | 3 ++- 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/fs_tree1.dts diff --git a/tests/fs_tree1.dts b/tests/fs_tree1.dts new file mode 100644 index 0000000..aeae436 --- /dev/null +++ b/tests/fs_tree1.dts @@ -0,0 +1,43 @@ +/dts-v1/; + +/ { + compatible = "test_tree1"; + #address-cells = <0x01>; + #size-cells = <0x00>; + prop-str = "hello world"; + prop-int = <0xdeadbeef>; + prop-int64 = <0xdeadbeef 0x1abcdef>; + + subnode@2 { + #address-cells = <0x01>; + linux,phandle = <0x2000>; + #size-cells = <0x00>; + reg = <0x02>; + prop-int = <0x75bcd15>; + + subsubnode@0 { + compatible = "subsubnode2\0subsubnode"; + phandle = <0x2001>; + reg = <0x00>; + prop-int = <0x75bcd15>; + }; + + ss2 { + }; + }; + + subnode@1 { + compatible = "subnode1"; + reg = <0x01>; + prop-int = <0xdeadbeef>; + + ss1 { + }; + + subsubnode { + compatible = "subsubnode1\0subsubnode"; + placeholder = "this is a placeholder string\0string2"; + prop-int = <0xdeadbeef>; + }; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 0e9f345..f8cc481 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -137,6 +137,19 @@ check_align () { ) } +# $1: first file +# $2: second file +files_equal () { + shorten_echo "files_equal $@: " + ( + if diff -q $1 $2; then + PASS + else + FAIL "File $1 differs from $2" + fi + ) +} + run_dtc_test () { printf "dtc $*: " base_run_test wrap_test $VALGRIND $DTC "$@" @@ -460,6 +473,7 @@ libfdt_tests () { run_dtc_test -I fs -O dts -o fs.test_tree1.test.dts $FSBASE/test_tree1 run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1 run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb + base_run_test files_equal fs_tree1.dts fs.test_tree1.test.dts # check full tests for good in test_tree1.dtb; do diff --git a/treesource.c b/treesource.c index c1fdb86..eabb929 100644 --- a/treesource.c +++ b/treesource.c @@ -64,6 +64,7 @@ static bool isstring(char c) static void write_propval_string(FILE *f, const char *s, size_t len) { const char *end = s + len - 1; + assert(len > 0); assert(*end == '\0'); fprintf(f, "\""); @@ -221,7 +222,7 @@ static void write_propval(FILE *f, struct property *prop) if (!next_type_marker(m)) { /* data type information missing, need to guess */ dummy_marker.type = guess_value_type(prop); - dummy_marker.next = prop->val.markers; + dummy_marker.next = NULL; dummy_marker.offset = 0; dummy_marker.ref = NULL; m = &dummy_marker; -- 2.19.0