Re: [PATCH v2] treesource: When using a dummy marker, replace the existing ones

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



On Wed, 2018-10-03 at 11:08 -0500, Rob Herring wrote:
> On Wed, Oct 3, 2018 at 8:22 AM Lubomir Rintel <lkundrak@xxxxx> wrote:
> > 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
> 
> You mean TYPE_NONE?

Yes.

> > 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 slightly confused as to when this is broken. This sounds like the
> output from fs input is completely broken for all strings, but I don't
> think that is true given we've had reports of only minor issues.

Yes, it's indeed broken for all strings. On my system:

$ ./dtc -I fs -O dts tests/fs/test_tree1 |grep '"'
  compatible = """test_tree1";
  prop-str = """hello world";
      compatible = """subsubnode2\0subsubnode";
    compatible = """subnode1";
      compatible = """subsubnode1\0subsubnode";
      placeholder = """this is a placeholder string\0string2";

Note the extra "". But also:

$ valgrind ./dtc -I fs -O dts tests/fs/test_tree1 |grep '"'
==178070== Memcheck, a memory error detector
==178070== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et
al.
==178070== Using Valgrind-3.13.0 and LibVEX; rerun with -h for
copyright info
==178070== Command: ./dtc -I fs -O dts tests/fs/test_tree1
==178070==
==178070== Invalid read of size 1
==178070==    at 0x40A547: write_propval_string (treesource.c:67)
==178070==    by 0x40A547: write_propval (treesource.c:259)
==178070==    by 0x40A547: write_tree_source_node (treesource.c:294)
==178070==    by 0x402AC5: main (dtc.c:357)
==178070==  Address 0x4a8447f is 1 bytes before a block of size 11
alloc'd
==178070==    at 0x4838748: malloc (vg_replace_malloc.c:298)
==178070==    by 0x483A9AF: realloc (vg_replace_malloc.c:785)
==178070==    by 0x405FCB: xrealloc (util.h:64)
==178070==    by 0x405FCB: data_grow_for (data.c:54)
==178070==    by 0x40661A: data_copy_file (data.c:107)
==178070==    by 0x40833F: read_fstree (fstree.c:61)
==178070==    by 0x4083D4: dt_from_fs (fstree.c:86)
==178070==    by 0x40294E: main (dtc.c:308)
==178070==
==178070== Invalid read of size 1
==178070==    at 0x40A547: write_propval_string (treesource.c:67)
==178070==    by 0x40A547: write_propval (treesource.c:259)
==178070==    by 0x40A547: write_tree_source_node (treesource.c:294)
==178070==    by 0x40A74A: write_tree_source_node (treesource.c:298)
==178070==    by 0x40A74A: write_tree_source_node (treesource.c:298)
==178070==    by 0x402AC5: main (dtc.c:357)
==178070==  Address 0x4a999ff is 1 bytes before a block of size 23
alloc'd
==178070==    at 0x4838748: malloc (vg_replace_malloc.c:298)
==178070==    by 0x483A9AF: realloc (vg_replace_malloc.c:785)
==178070==    by 0x405FCB: xrealloc (util.h:64)
==178070==    by 0x405FCB: data_grow_for (data.c:54)
==178070==    by 0x40661A: data_copy_file (data.c:107)
==178070==    by 0x40833F: read_fstree (fstree.c:61)
==178070==    by 0x40838B: read_fstree (fstree.c:70)
==178070==    by 0x40838B: read_fstree (fstree.c:70)
==178070==    by 0x4083D4: dt_from_fs (fstree.c:86)
==178070==    by 0x40294E: main (dtc.c:308)
==178070==
==178070== Invalid read of size 1
==178070==    at 0x40A547: write_propval_string (treesource.c:67)
==178070==    by 0x40A547: write_propval (treesource.c:259)
==178070==    by 0x40A547: write_tree_source_node (treesource.c:294)
==178070==    by 0x40A74A: write_tree_source_node (treesource.c:298)
==178070==    by 0x402AC5: main (dtc.c:357)
==178070==  Address 0x4ab578f is 1 bytes before a block of size 9
alloc'd
==178070==    at 0x4838748: malloc (vg_replace_malloc.c:298)
==178070==    by 0x483A9AF: realloc (vg_replace_malloc.c:785)
==178070==    by 0x405FCB: xrealloc (util.h:64)
==178070==    by 0x405FCB: data_grow_for (data.c:54)
==178070==    by 0x40661A: data_copy_file (data.c:107)
==178070==    by 0x40833F: read_fstree (fstree.c:61)
==178070==    by 0x40838B: read_fstree (fstree.c:70)
==178070==    by 0x4083D4: dt_from_fs (fstree.c:86)
==178070==    by 0x40294E: main (dtc.c:308)

> 
> > 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";
> 
> The fs input having '\0' output is a bug BTW. I need to respin my fix,
> but these 2 patches will collide.
> 
> > +                       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);
> 
> This can and will happen with REF_PATH markers. See "Fix dts output
> with a REF_PATH marker" patch which David said he applied, but looks
> like he hasn't pushed out yet.
> 
> >         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;

I'm now going to wait until the \0 fix and David's patch you mentioned
lands before I send out a v3.

Thanks
Lubo




[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux