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;
        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;
                }
 
        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;
        }
 
        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)))
 
        /* 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
 
 void fit_conf_print(const void *fit, int noffset, const char *p)
 {
        char *desc;
-       char *uname;
+       const char *uname;
        int ret;
        int loadables_index;
 
        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");
                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 {
 
        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);
        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;
                }
        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)) {
                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,
 
 
        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;
        }
 
 
 #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;
 
                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;
 
 
         * 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 {
 
 
        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;
        }
 
 
        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;
 
 {
        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;
         * 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;
 
        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);
 
 
        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;
 
 
        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 */
        }
 
        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)
 
        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;
                /*
 
        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;
        }
 
 
        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;
 
        /* 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)                */
 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)                           */
 
 {
        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;
 
 
        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,
 
                           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)