diff options
Diffstat (limited to 'scripts/dtc/libfdt/fdt.c')
| -rw-r--r-- | scripts/dtc/libfdt/fdt.c | 61 | 
1 files changed, 41 insertions, 20 deletions
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 2acaec5923a..e56833ae9b6 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)  	return 0;  } -const void *fdt_offset_ptr(const void *fdt, int offset, int len) +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)  {  	const char *p; @@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, 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;  } @@ -138,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset)  	return offset;  } +int _fdt_check_prop_offset(const void *fdt, int offset) +{ +	if ((offset < 0) || (offset % FDT_TAGSIZE) +	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) +		return -FDT_ERR_BADOFFSET; + +	return offset; +} +  int fdt_next_node(const void *fdt, int offset, int *depth)  {  	int nextoffset = 0; @@ -162,15 +182,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth)  			break;  		case FDT_END_NODE: -			if (depth) -				(*depth)--; +			if (depth && ((--(*depth)) < 0)) +				return nextoffset;  			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);  | 
