diff --git a/arch/arm/mach-tegra/xusb-padctl-common.c b/arch/arm/mach-tegra/xusb-padctl-common.c
index 18ad7bfbdc0f7fa862bb735c4fb29827b3c9b83f..6867065790f40ee3f709648c3b6d37fe8f179ec0 100644
--- a/arch/arm/mach-tegra/xusb-padctl-common.c
+++ b/arch/arm/mach-tegra/xusb-padctl-common.c
@@ -78,11 +78,11 @@ tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
 				 const void *fdt, int node)
 {
 	unsigned int i;
-	int len, err;
+	int len;
 
 	group->name = fdt_get_name(fdt, node, &len);
 
-	len = fdt_count_strings(fdt, node, "nvidia,lanes");
+	len =  fdt_stringlist_count(fdt, node, "nvidia,lanes");
 	if (len < 0) {
 		error("failed to parse \"nvidia,lanes\" property");
 		return -EINVAL;
@@ -91,9 +91,9 @@ tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
 	group->num_pins = len;
 
 	for (i = 0; i < group->num_pins; i++) {
-		err = fdt_get_string_index(fdt, node, "nvidia,lanes", i,
-					   &group->pins[i]);
-		if (err < 0) {
+		group->pins[i] = fdt_stringlist_get(fdt, node, "nvidia,lanes",
+						    i, NULL);
+		if (!group->pins[i]) {
 			error("failed to read string from \"nvidia,lanes\" property");
 			return -EINVAL;
 		}
@@ -101,8 +101,8 @@ tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
 
 	group->num_pins = len;
 
-	err = fdt_get_string(fdt, node, "nvidia,function", &group->func);
-	if (err < 0) {
+	group->func = fdt_stringlist_get(fdt, node, "nvidia,function", 0, NULL);
+	if (!group->func) {
 		error("failed to parse \"nvidia,func\" property");
 		return -EINVAL;
 	}
diff --git a/arch/arm/mach-uniphier/board_late_init.c b/arch/arm/mach-uniphier/board_late_init.c
index a45412677a0ffcfad93ca01f7a6ee222471f90ce..f23295fbd2128016318a72368d62facba60e6e2a 100644
--- a/arch/arm/mach-uniphier/board_late_init.c
+++ b/arch/arm/mach-uniphier/board_late_init.c
@@ -37,13 +37,12 @@ static int uniphier_set_fdt_file(void)
 	const char *compat;
 	char dtb_name[256];
 	int buf_len = 256;
-	int ret;
 
 	if (getenv("fdt_file"))
 		return 0;	/* do nothing if it is already set */
 
-	ret = fdt_get_string(gd->fdt_blob, 0, "compatible", &compat);
-	if (ret)
+	compat = fdt_stringlist_get(gd->fdt_blob, 0, "compatible", 0, NULL);
+	if (!compat)
 		return -EINVAL;
 
 	if (strncmp(compat, VENDOR_PREFIX, strlen(VENDOR_PREFIX)))
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c
index df3cd0abc7771bef450f70c458ad13613d2162e4..9364410a0f83728854df8b01c40e2d369334bf4b 100644
--- a/arch/x86/cpu/irq.c
+++ b/arch/x86/cpu/irq.c
@@ -103,11 +103,12 @@ static int create_pirq_routing_table(struct udevice *dev)
 	/* extract the bdf from fdt_pci_addr */
 	priv->bdf = dm_pci_get_bdf(dev->parent);
 
-	ret = fdt_find_string(blob, node, "intel,pirq-config", "pci");
+	ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci");
 	if (!ret) {
 		priv->config = PIRQ_VIA_PCI;
 	} else {
-		ret = fdt_find_string(blob, node, "intel,pirq-config", "ibase");
+		ret = fdt_stringlist_search(blob, node, "intel,pirq-config",
+					    "ibase");
 		if (!ret)
 			priv->config = PIRQ_VIA_IBASE;
 		else
diff --git a/common/image-fit.c b/common/image-fit.c
index 1b0234a90cb1eefcc7533f630491e8a68098292a..d67678a6dd56bd57623e2a90820328125c89491a 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1457,7 +1457,7 @@ int fit_conf_get_prop_node(const void *fit, int noffset,
 void fit_conf_print(const void *fit, int noffset, const char *p)
 {
 	char *desc;
-	char *uname;
+	const char *uname;
 	int ret;
 	int loadables_index;
 
@@ -1469,7 +1469,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
 	else
 		printf("%s\n", desc);
 
-	uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
+	uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
 	printf("%s  Kernel:       ", p);
 	if (uname == NULL)
 		printf("unavailable\n");
@@ -1477,26 +1477,23 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
 		printf("%s\n", uname);
 
 	/* Optional properties */
-	uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
+	uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
 	if (uname)
 		printf("%s  Init Ramdisk: %s\n", p, uname);
 
-	uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
+	uname = fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
 	if (uname)
 		printf("%s  FDT:          %s\n", p, uname);
 
-	uname = (char *)fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
+	uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
 	if (uname)
 		printf("%s  FPGA:         %s\n", p, uname);
 
 	/* Print out all of the specified loadables */
 	for (loadables_index = 0;
-	     fdt_get_string_index(fit, noffset,
-			FIT_LOADABLE_PROP,
-			loadables_index,
-			(const char **)&uname) == 0;
-	     loadables_index++)
-	{
+	     uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
+					loadables_index, NULL), uname;
+	     loadables_index++) {
 		if (loadables_index == 0) {
 			printf("%s  Loadables:    ", p);
 		} else {
diff --git a/common/image.c b/common/image.c
index c0ad36a60f8a90c6ef31d65816dae30441b3de8d..0e86c13a88aa827415d98740894abe12440ed91f 100644
--- a/common/image.c
+++ b/common/image.c
@@ -1305,7 +1305,7 @@ int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
 	void *buf;
 	int conf_noffset;
 	int fit_img_result;
-	char *uname, *name;
+	const char *uname, *name;
 	int err;
 	int devnum = 0; /* TODO support multi fpga platforms */
 	const fpga_desc * const desc = fpga_get_desc(devnum);
@@ -1332,9 +1332,9 @@ int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
 	case IMAGE_FORMAT_FIT:
 		conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
 
-		err = fdt_get_string_index(buf, conf_noffset, FIT_FPGA_PROP, 0,
-					   (const char **)&uname);
-		if (err < 0) {
+		uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0,
+					   NULL);
+		if (!uname) {
 			debug("## FPGA image is not specified\n");
 			return 0;
 		}
@@ -1404,7 +1404,7 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
 	int loadables_index;
 	int conf_noffset;
 	int fit_img_result;
-	char *uname;
+	const char *uname;
 
 	/* Check to see if the images struct has a FIT configuration */
 	if (!genimg_has_config(images)) {
@@ -1428,15 +1428,14 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
 		conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
 
 		for (loadables_index = 0;
-		     fdt_get_string_index(buf, conf_noffset,
-				FIT_LOADABLE_PROP,
-				loadables_index,
-				(const char **)&uname) == 0;
+		     uname = fdt_stringlist_get(buf, conf_noffset,
+					FIT_LOADABLE_PROP, loadables_index,
+					NULL), uname;
 		     loadables_index++)
 		{
 			fit_img_result = fit_image_load(images,
 				tmp_img_addr,
-				(const char **)&uname,
+				&uname,
 				&(images->fit_uname_cfg), arch,
 				IH_TYPE_LOADABLE,
 				BOOTSTAGE_ID_FIT_LOADABLE_START,
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 4d78e3fcac43d586ea5f2dc02cd5bb7fb48ab51c..c42fff6ec2908ba801d8420011b7e55f4346da9a 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -101,10 +101,10 @@ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
 
 	debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
 
-	index = fdt_find_string(gd->fdt_blob, dev->of_offset, "clock-names",
-				name);
+	index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset,
+				      "clock-names", name);
 	if (index < 0) {
-		debug("fdt_find_string() failed: %d\n", index);
+		debug("fdt_stringlist_search() failed: %d\n", index);
 		return index;
 	}
 
diff --git a/drivers/core/device.c b/drivers/core/device.c
index b737f1c78907ada6e7538ed9262f2a49d9246386..1935b8d46f1eefe20f6a4cb009f2b2a56f122da1 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -698,7 +698,7 @@ fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name)
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 	int index;
 
-	index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reg-names",
+	index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset, "reg-names",
 				name);
 	if (index < 0)
 		return index;
diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c
index 72cec488009597900d287ea3ed5eaf9e38565e2d..471e18aeaa0b3c54091a100214dab6ab735ff69c 100644
--- a/drivers/gpio/dwapb_gpio.c
+++ b/drivers/gpio/dwapb_gpio.c
@@ -132,7 +132,8 @@ static int gpio_dwapb_bind(struct udevice *dev)
 		plat->base = base;
 		plat->bank = bank;
 		plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0);
-		ret = fdt_get_string(blob, node, "bank-name", &plat->name);
+		plat->name = fdt_stringlist_get(blob, node, "bank-name", 0,
+						NULL);
 		if (ret)
 			goto err;
 
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index a26f44e1e60edb8f4dceb701f14f335fea75406c..6247d334a0b21b8dd6a9402365c5551e9319b4b6 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -773,7 +773,7 @@ static int mxc_i2c_probe(struct udevice *bus)
 	 * See Documentation/devicetree/bindings/i2c/i2c-imx.txt
 	 * Use gpio to force bus idle when necessary.
 	 */
-	ret = fdt_find_string(fdt, node, "pinctrl-names", "gpio");
+	ret = fdt_stringlist_search(fdt, node, "pinctrl-names", "gpio");
 	if (ret < 0) {
 		dev_info(dev, "i2c bus %d at %lu, no gpio pinctrl state.\n", bus->seq, i2c_bus->base);
 	} else {
diff --git a/drivers/mailbox/mailbox-uclass.c b/drivers/mailbox/mailbox-uclass.c
index 40f851d915490e793326588b2831c66523802c7b..a7fcde51d593a105a3f49db713993958b533bea8 100644
--- a/drivers/mailbox/mailbox-uclass.c
+++ b/drivers/mailbox/mailbox-uclass.c
@@ -85,10 +85,10 @@ int mbox_get_by_name(struct udevice *dev, const char *name,
 
 	debug("%s(dev=%p, name=%s, chan=%p)\n", __func__, dev, name, chan);
 
-	index = fdt_find_string(gd->fdt_blob, dev->of_offset, "mbox-names",
-				name);
+	index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset,
+				      "mbox-names", name);
 	if (index < 0) {
-		debug("fdt_find_string() failed: %d\n", index);
+		debug("fdt_stringlist_search() failed: %d\n", index);
 		return index;
 	}
 
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 4c149e1bdf2c1aa78e8680c0a8b119bd4b72a4b2..91570a29106f6d5ccd8ba80be7c976d097c8e8d9 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -456,8 +456,9 @@ static int parse_phy_pins(struct udevice *dev)
 	for (i = 0; ; i++) {
 		int pin;
 
-		if (fdt_get_string_index(gd->fdt_blob, offset,
-					 "allwinner,pins", i, &pin_name))
+		pin_name = fdt_stringlist_get(gd->fdt_blob, offset,
+					 "allwinner,pins", i, NULL);
+		if (!pin_name)
 			break;
 		if (pin_name[0] != 'P')
 			continue;
diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c
index a28405fc155fbbdeecc612ff8d7a5a06c499c7de..c9c13e68028f6272b8ceb27516ece0b369447901 100644
--- a/drivers/pinctrl/exynos/pinctrl-exynos.c
+++ b/drivers/pinctrl/exynos/pinctrl-exynos.c
@@ -71,7 +71,7 @@ int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config)
 {
 	const void *fdt = gd->fdt_blob;
 	int node = config->of_offset;
-	unsigned int count, idx, pin_num, ret;
+	unsigned int count, idx, pin_num;
 	unsigned int pinfunc, pinpud, pindrv;
 	unsigned long reg, value;
 	const char *name;
@@ -80,7 +80,7 @@ int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config)
 	 * refer to the following document for the pinctrl bindings
 	 * linux/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
 	 */
-	count = fdt_count_strings(fdt, node, "samsung,pins");
+	count =  fdt_stringlist_count(fdt, node, "samsung,pins");
 	if (count <= 0)
 		return -EINVAL;
 
@@ -89,9 +89,8 @@ int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config)
 	pindrv = fdtdec_get_int(fdt, node, "samsung,pin-drv", -1);
 
 	for (idx = 0; idx < count; idx++) {
-		ret = fdt_get_string_index(fdt, node, "samsung,pins",
-						idx, &name);
-		if (ret < 0)
+		name = fdt_stringlist_get(fdt, node, "samsung,pins", idx, NULL);
+		if (!name)
 			continue;
 		reg = pin_to_bank_base(dev, name, &pin_num);
 
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index d21a3dd75522cb012ea98f2c9ceccfb1b5b04446..46470eaae94f97a6894bb7bb2684875bd95c42cd 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -122,7 +122,7 @@ static fdt_addr_t parse_address(int offset, const char *name, int na, int ns)
 	int index, len = 0;
 	const fdt32_t *reg;
 
-	index = fdt_find_string(gd->fdt_blob, offset, "reg-names", name);
+	index = fdt_stringlist_search(gd->fdt_blob, offset, "reg-names", name);
 	if (index < 0)
 		return FDT_ADDR_T_NONE;
 
diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
index baff40f1f0d4141c6af80718009e22453855d733..482db295fee1c8eaf995d4c869f4d0a026e858bc 100644
--- a/drivers/pinctrl/pinctrl-generic.c
+++ b/drivers/pinctrl/pinctrl-generic.c
@@ -306,11 +306,11 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
 	const char *name;
 	int strings_count, selector, i, ret;
 
-	strings_count = fdt_count_strings(fdt, node, subnode_target_type);
+	strings_count =  fdt_stringlist_count(fdt, node, subnode_target_type);
 	if (strings_count < 0) {
 		subnode_target_type = "groups";
 		is_group = true;
-		strings_count = fdt_count_strings(fdt, node,
+		strings_count =  fdt_stringlist_count(fdt, node,
 						  subnode_target_type);
 		if (strings_count < 0) {
 			/* skip this node; may contain config child nodes */
@@ -319,9 +319,9 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
 	}
 
 	for (i = 0; i < strings_count; i++) {
-		ret = fdt_get_string_index(fdt, node, subnode_target_type,
-					   i, &name);
-		if (ret < 0)
+		name = fdt_stringlist_get(fdt, node, subnode_target_type, i,
+					  NULL);
+		if (!name)
 			return -EINVAL;
 
 		if (is_group)
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 7397de28c0142fb63f03403f63b0786703dbbc65..02ab9b4afde6499ad9deee4b68fcd6b4b7947cd7 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -72,7 +72,7 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
 	struct udevice *config;
 	int state, size, i, ret;
 
-	state = fdt_find_string(fdt, node, "pinctrl-names", statename);
+	state = fdt_stringlist_search(fdt, node, "pinctrl-names", statename);
 	if (state < 0) {
 		char *end;
 		/*
diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index edaecfbc99b1ee9ca2bad669101038d811b0020a..d3744ef703cbb1f7976f3ca6a778a6f094ff62b7 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -88,10 +88,10 @@ int reset_get_by_name(struct udevice *dev, const char *name,
 	debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name,
 	      reset_ctl);
 
-	index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reset-names",
-				name);
+	index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset,
+				      "reset-names", name);
 	if (index < 0) {
-		debug("fdt_find_string() failed: %d\n", index);
+		debug("fdt_stringlist_search() failed: %d\n", index);
 		return index;
 	}
 
diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c
index 50b16a9129f8e10aa19bc9507ce2ed33d2e41444..6cba1b95a110528dbda9d29d9370a7613f60d6d6 100644
--- a/drivers/video/sunxi_display.c
+++ b/drivers/video/sunxi_display.c
@@ -1562,7 +1562,7 @@ int sunxi_simplefb_setup(void *blob)
 	offset = fdt_node_offset_by_compatible(blob, -1,
 					       "allwinner,simple-framebuffer");
 	while (offset >= 0) {
-		ret = fdt_find_string(blob, offset, "allwinner,pipeline",
+		ret = fdt_stringlist_search(blob, offset, "allwinner,pipeline",
 				      pipeline);
 		if (ret == 0)
 			break;
diff --git a/include/libfdt.h b/include/libfdt.h
index 3b1c788f492718c022091f69846ae262b1ea40e6..f3b61c94271ad57cd4d5395fa155ff7fa0cb4d70 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -121,12 +121,17 @@
 	/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
 	 * or similar property with a bad format or value */
 
-#define FDT_ERR_TOODEEP		15
+#define FDT_ERR_BADVALUE	15
+	/* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
+	 * value. For example: a property expected to contain a string list
+	 * is not NUL-terminated within the length of its value. */
+
+#define FDT_ERR_TOODEEP		16
 	/* FDT_ERR_TOODEEP: The depth of a node has exceeded the internal
 	 * libfdt limit. This can happen if you have more than
 	 * FDT_MAX_DEPTH nested nodes. */
 
-#define FDT_ERR_MAX		15
+#define FDT_ERR_MAX		16
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -957,51 +962,66 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
 /**
- * fdt_count_strings - count the number of strings in a string list
+ * fdt_stringlist_count - count the number of strings in a string list
  * @fdt: pointer to the device tree blob
- * @node: offset of the node
+ * @nodeoffset: offset of a tree node
  * @property: name of the property containing the string list
- * @return: the number of strings in the given property
+ * @return:
+ *   the number of strings in the given property
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist
  */
-int fdt_count_strings(const void *fdt, int node, const char *property);
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
 
 /**
- * fdt_find_string - find a string in a string list and return its index
+ * fdt_stringlist_search - find a string in a string list and return its index
  * @fdt: pointer to the device tree blob
- * @node: offset of the node
+ * @nodeoffset: offset of a tree node
  * @property: name of the property containing the string list
  * @string: string to look up in the string list
- * @return: the index of the string or negative on error
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
+ *                     the given string
  */
-int fdt_find_string(const void *fdt, int node, const char *property,
-		    const char *string);
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+			  const char *string);
 
 /**
- * fdt_get_string_index() - obtain the string at a given index in a string list
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
  * @fdt: pointer to the device tree blob
- * @node: offset of the node
+ * @nodeoffset: offset of a tree node
  * @property: name of the property containing the string list
  * @index: index of the string to return
- * @output: return location for the string
- * @return: 0 if the string was found or a negative error code otherwise
- */
-int fdt_get_string_index(const void *fdt, int node, const char *property,
-			 int index, const char **output);
-
-/**
- * fdt_get_string() - obtain the first string in a string list
- * @fdt: pointer to the device tree blob
- * @node: offset of the node
- * @property: name of the property containing the string list
- * @output: return location for the string
- * @return: 0 if the string was found or a negative error code otherwise
- *
- * This is a shortcut for:
- *
- *	fdt_get_string_index(fdt, node, property, 0, output).
- */
-int fdt_get_string(const void *fdt, int node, const char *property,
-		   const char **output);
+ * @lenp: return location for the string length or an error code on failure
+ *
+ * Note that this will successfully extract strings from properties with
+ * non-NUL-terminated values. For example on small-valued cell properties
+ * this function will return the empty string.
+ *
+ * If non-NULL, the length of the string (on success) or a negative error-code
+ * (on failure) will be stored in the integer pointer to by lenp.
+ *
+ * @return:
+ *   A pointer to the string at the given index in the string list or NULL on
+ *   failure. On success the length of the string will be stored in the memory
+ *   location pointed to by the lenp parameter, if non-NULL. On failure one of
+ *   the following negative error codes will be returned in the lenp parameter
+ *   (if non-NULL):
+ *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *     -FDT_ERR_NOTFOUND if the property does not exist
+ */
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+			       const char *property, int index,
+			       int *lenp);
 
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 4defb902b87297d03f891ea18b26647bd19fccc9..adc9975c3610f6b8d480f9ec0ff8eb7cb6865be5 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1014,7 +1014,7 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
 {
 	int index;
 
-	index = fdt_find_string(fdt, node, prop_names, name);
+	index = fdt_stringlist_search(fdt, node, prop_names, name);
 	if (index < 0)
 		return index;
 
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 005f26736f8f2c7f37c1985a1c24daa703a9f02a..e38aaa4ccf9ace9f3544a291180dcc359f9ebedb 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -538,80 +538,104 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
 	return 0;
 }
 
-int fdt_count_strings(const void *fdt, int node, const char *property)
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
 {
-	int length, i, count = 0;
-	const char *list;
+	const char *list, *end;
+	int length, count = 0;
 
-	list = fdt_getprop(fdt, node, property, &length);
+	list = fdt_getprop(fdt, nodeoffset, property, &length);
 	if (!list)
-		return length;
+		return -length;
+
+	end = list + length;
+
+	while (list < end) {
+		length = strnlen(list, end - list) + 1;
 
-	for (i = 0; i < length; i++) {
-		int len = strlen(list);
+		/* Abort if the last string isn't properly NUL-terminated. */
+		if (list + length > end)
+			return -FDT_ERR_BADVALUE;
 
-		list += len + 1;
-		i += len;
+		list += length;
 		count++;
 	}
 
 	return count;
 }
 
-int fdt_find_string(const void *fdt, int node, const char *property,
-		    const char *string)
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+			  const char *string)
 {
+	int length, len, idx = 0;
 	const char *list, *end;
-	int len, index = 0;
 
-	list = fdt_getprop(fdt, node, property, &len);
+	list = fdt_getprop(fdt, nodeoffset, property, &length);
 	if (!list)
-		return len;
+		return -length;
 
-	end = list + len;
-	len = strlen(string);
+	len = strlen(string) + 1;
+	end = list + length;
 
 	while (list < end) {
-		int l = strlen(list);
+		length = strnlen(list, end - list) + 1;
+
+		/* Abort if the last string isn't properly NUL-terminated. */
+		if (list + length > end)
+			return -FDT_ERR_BADVALUE;
 
-		if (l == len && memcmp(list, string, len) == 0)
-			return index;
+		if (length == len && memcmp(list, string, length) == 0)
+			return idx;
 
-		list += l + 1;
-		index++;
+		list += length;
+		idx++;
 	}
 
 	return -FDT_ERR_NOTFOUND;
 }
 
-int fdt_get_string_index(const void *fdt, int node, const char *property,
-			 int index, const char **output)
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+			       const char *property, int idx,
+			       int *lenp)
 {
-	const char *list;
-	int length, i;
+	const char *list, *end;
+	int length;
+
+	list = fdt_getprop(fdt, nodeoffset, property, &length);
+	if (!list) {
+		if (lenp)
+			*lenp = length;
 
-	list = fdt_getprop(fdt, node, property, &length);
+		return NULL;
+	}
 
-	for (i = 0; i < length; i++) {
-		int len = strlen(list);
+	end = list + length;
 
-		if (index == 0) {
-			*output = list;
-			return 0;
+	while (list < end) {
+		length = strnlen(list, end - list) + 1;
+
+		/* Abort if the last string isn't properly NUL-terminated. */
+		if (list + length > end) {
+			if (lenp)
+				*lenp = -FDT_ERR_BADVALUE;
+
+			return NULL;
+		}
+
+		if (idx == 0) {
+			if (lenp)
+				*lenp = length - 1;
+
+			return list;
 		}
 
-		list += len + 1;
-		i += len;
-		index--;
+		list += length;
+		idx--;
 	}
 
-	return -FDT_ERR_NOTFOUND;
-}
+	if (lenp)
+		*lenp = -FDT_ERR_NOTFOUND;
 
-int fdt_get_string(const void *fdt, int node, const char *property,
-		   const char **output)
-{
-	return fdt_get_string_index(fdt, node, property, 0, output);
+	return NULL;
 }
 
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
index 87dc9328c674bda7f13773e3183b7b2ba9983208..cbef720b4c091fd0b8075e0c60ca852b582032ff 100644
--- a/test/overlay/cmd_ut_overlay.c
+++ b/test/overlay/cmd_ut_overlay.c
@@ -52,12 +52,15 @@ static int fdt_getprop_str(void *fdt, const char *path, const char *name,
 			   const char **out)
 {
 	int node_off;
+	int len;
 
 	node_off = fdt_path_offset(fdt, path);
 	if (node_off < 0)
 		return node_off;
 
-	return fdt_get_string(fdt, node_off, name, out);
+	*out = fdt_stringlist_get(fdt, node_off, name, 0, &len);
+
+	return len < 0 ? len : 0;
 }
 
 static int fdt_overlay_change_int_property(struct unit_test_state *uts)