From a22d9cfbb5bcfb3dc6ffd64d391b568e8a0ce383 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 6 Feb 2009 14:03:24 +1100 Subject: libfdt: Rework/cleanup fdt_next_tag() Currently, callers of fdt_next_tag() must usually follow the call with some sort of call to fdt_offset_ptr() to verify that the blob isn't truncated in the middle of the tag data they're going to process. This is a bit silly, since fdt_next_tag() generally has to call fdt_offset_ptr() on at least some of the data following the tag for its own operation. This patch alters fdt_next_tag() to always use fdt_offset_ptr() to verify the data between its starting offset and the offset it returns in nextoffset. This simplifies fdt_get_property() which no longer has to verify itself that the property data is all present. At the same time, I neaten and clarify the error handling for fdt_next_tag(). Previously, fdt_next_tag() could return -1 instead of a tag value in some circumstances - which almost none of the callers checked for. Also, fdt_next_tag() could return FDT_END either because it encountered an FDT_END tag, or because it reached the end of the structure block - no way was provided to tell between these cases. With this patch, fdt_next_tag() always returns FDT_END with a negative value in nextoffset for an error. This means the several places which loop looking for FDT_END will still work correctly - they only need to check for errors at the end. The errors which fdt_next_tag() can report are: - -FDT_ERR_TRUNCATED if it reached the end of the structure block instead of finding a tag. - -FDT_BADSTRUCTURE if a bad tag was encountered, or if the tag data couldn't be verified with fdt_offset_ptr(). This patch also updates the callers of fdt_next_tag(), where appropriate, to make use of the new error reporting. Finally, the prototype for the long gone _fdt_next_tag() is removed from libfdt_internal.h. Signed-off-by: David Gibson --- libfdt/fdt_ro.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) (limited to 'libfdt/fdt_ro.c') diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index d682a40c1..1e1e32209 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -205,7 +205,6 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, { uint32_t tag; const struct fdt_property *prop; - int namestroff; int offset, nextoffset; int err; @@ -220,38 +219,24 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: - err = -FDT_ERR_TRUNCATED; + if (nextoffset < 0) + err = nextoffset; + else + /* FDT_END tag with unclosed nodes */ + err = -FDT_ERR_BADSTRUCTURE; goto fail; - case FDT_BEGIN_NODE: - case FDT_END_NODE: - case FDT_NOP: - break; - case FDT_PROP: - err = -FDT_ERR_BADSTRUCTURE; - prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); - if (! prop) - goto fail; - namestroff = fdt32_to_cpu(prop->nameoff); - if (_fdt_string_eq(fdt, namestroff, name, namelen)) { + prop = _fdt_offset_ptr(fdt, offset); + if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), + name, namelen)) { /* Found it! */ - int len = fdt32_to_cpu(prop->len); - prop = fdt_offset_ptr(fdt, offset, - sizeof(*prop)+len); - if (! prop) - goto fail; - if (lenp) - *lenp = len; + *lenp = fdt32_to_cpu(prop->len); return prop; } break; - - default: - err = -FDT_ERR_BADSTRUCTURE; - goto fail; } } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); -- cgit v1.2.3