[U-Boot] libfdt: Fix bugs in fdt_get_path()
Jerry Van Baren
gvb.uboot at gmail.com
Sat Aug 30 18:13:11 CEST 2008
FYI, I propose to pick this up for the *NEXT* release of u-boot ("Yellow
Submarine" ;-). My reasoning is that (1) the current window closes
today, which makes me uncomfortable WRT putting in changes today and (2)
this appears to be a latent bug (at worst, a misleading error message);
I have not seen evidence that it is causing problems at the moment.
Best regards,
gvb
David Gibson wrote:
> The current implementation of fdt_get_path() has a couple of bugs,
> fixed by this patch.
>
> First, contrary to its documentation, on success it returns the length
> of the node's path, rather than 0. The testcase is correspondingly
> wrong, and the patch fixes this as well.
>
> Second, in some circumstances, it will return -FDT_ERR_BADOFFSET
> instead of -FDT_ERR_NOSPACE when given insufficient buffer space.
> Specifically this happens when there is insufficient space even to
> hold the path's second last component. This behaviour is corrected,
> and the testcase updated to check it.
>
> Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
>
> Index: dtc/tests/get_path.c
> ===================================================================
> --- dtc.orig/tests/get_path.c 2008-08-29 14:11:09.000000000 +1000
> +++ dtc/tests/get_path.c 2008-08-29 14:11:11.000000000 +1000
> @@ -43,6 +43,8 @@ static void check_path_buf(void *fdt, co
> memset(buf, POISON, sizeof(buf)); /* poison the buffer */
>
> len = fdt_get_path(fdt, offset, buf, buflen);
> + verbose_printf("get_path() %s -> %d -> %s\n", path, offset, buf);
> +
> if (buflen <= pathlen) {
> if (len != -FDT_ERR_NOSPACE)
> FAIL("fdt_get_path([%d bytes]) returns %d with "
> @@ -51,9 +53,9 @@ static void check_path_buf(void *fdt, co
> if (len < 0)
> FAIL("fdt_get_path([%d bytes]): %s", buflen,
> fdt_strerror(len));
> - if (len != pathlen)
> - FAIL("fdt_get_path([%d bytes]) reports length %d "
> - "instead of %d", buflen, len, pathlen);
> + if (len != 0)
> + FAIL("fdt_get_path([%d bytes]) returns %d "
> + "instead of 0", buflen, len);
> if (strcmp(buf, path) != 0)
> FAIL("fdt_get_path([%d bytes]) returns \"%s\" "
> "instead of \"%s\"", buflen, buf, path);
> @@ -70,6 +72,8 @@ static void check_path(void *fdt, const
> check_path_buf(fdt, path, pathlen, 1024);
> check_path_buf(fdt, path, pathlen, pathlen+1);
> check_path_buf(fdt, path, pathlen, pathlen);
> + check_path_buf(fdt, path, pathlen, 0);
> + check_path_buf(fdt, path, pathlen, 2);
> }
>
> int main(int argc, char *argv[])
> Index: dtc/libfdt/fdt_ro.c
> ===================================================================
> --- dtc.orig/libfdt/fdt_ro.c 2008-08-29 14:11:11.000000000 +1000
> +++ dtc/libfdt/fdt_ro.c 2008-08-29 14:11:11.000000000 +1000
> @@ -328,9 +328,6 @@ int fdt_get_path(const void *fdt, int no
> for (offset = 0, depth = 0;
> (offset >= 0) && (offset <= nodeoffset);
> offset = fdt_next_node(fdt, offset, &depth)) {
> - if (pdepth < depth)
> - continue; /* overflowed buffer */
> -
> while (pdepth > depth) {
> do {
> p--;
> @@ -338,14 +335,16 @@ int fdt_get_path(const void *fdt, int no
> pdepth--;
> }
>
> - name = fdt_get_name(fdt, offset, &namelen);
> - if (!name)
> - return namelen;
> - if ((p + namelen + 1) <= buflen) {
> - memcpy(buf + p, name, namelen);
> - p += namelen;
> - buf[p++] = '/';
> - pdepth++;
> + if (pdepth >= depth) {
> + name = fdt_get_name(fdt, offset, &namelen);
> + if (!name)
> + return namelen;
> + if ((p + namelen + 1) <= buflen) {
> + memcpy(buf + p, name, namelen);
> + p += namelen;
> + buf[p++] = '/';
> + pdepth++;
> + }
> }
>
> if (offset == nodeoffset) {
> @@ -355,7 +354,7 @@ int fdt_get_path(const void *fdt, int no
> if (p > 1) /* special case so that root path is "/", not "" */
> p--;
> buf[p] = '\0';
> - return p;
> + return 0;
> }
> }
>
>
More information about the U-Boot
mailing list