diff options
Diffstat (limited to 'libfdt/fdt.c')
| -rw-r--r-- | libfdt/fdt.c | 46 | 
1 files changed, 29 insertions, 17 deletions
| diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 940cee8b1..b09ea6f04 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -94,42 +94,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)  	return p;  } -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)  {  	const uint32_t *tagp, *lenp;  	uint32_t tag; +	int offset = startoffset;  	const char *p; -	if (offset % FDT_TAGSIZE) -		return -1; - +	*nextoffset = -FDT_ERR_TRUNCATED;  	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); -	if (! tagp) +	if (!tagp)  		return FDT_END; /* premature end */  	tag = fdt32_to_cpu(*tagp);  	offset += FDT_TAGSIZE; +	*nextoffset = -FDT_ERR_BADSTRUCTURE;  	switch (tag) {  	case FDT_BEGIN_NODE:  		/* skip name */  		do {  			p = fdt_offset_ptr(fdt, offset++, 1);  		} while (p && (*p != '\0')); -		if (! p) -			return FDT_END; +		if (!p) +			return FDT_END; /* premature end */  		break; +  	case FDT_PROP:  		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); -		if (! lenp) -			return FDT_END; -		/* skip name offset, length and value */ -		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); +		if (!lenp) +			return FDT_END; /* premature end */ +		/* skip-name offset, length and value */ +		offset += sizeof(struct fdt_property) - FDT_TAGSIZE +			+ fdt32_to_cpu(*lenp); +		break; + +	case FDT_END: +	case FDT_END_NODE: +	case FDT_NOP:  		break; + +	default: +		return FDT_END;  	} -	if (nextoffset) -		*nextoffset = FDT_TAGALIGN(offset); +	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) +		return FDT_END; /* premature end */ +	*nextoffset = FDT_TAGALIGN(offset);  	return tag;  } @@ -171,10 +182,11 @@ int fdt_next_node(const void *fdt, int offset, int *depth)  			break;  		case FDT_END: -			return -FDT_ERR_NOTFOUND; - -		default: -			return -FDT_ERR_BADSTRUCTURE; +			if ((nextoffset >= 0) +			    || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) +				return -FDT_ERR_NOTFOUND; +			else +				return nextoffset;  		}  	} while (tag != FDT_BEGIN_NODE); |