#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/limits.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
return 0;
}
+static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset)
+{
+ const u8 *start;
+ const u8 *nul;
+ size_t remaining;
+ size_t len;
+
+ if (offset < 0 || offset >= fmw->size)
+ return -EINVAL;
+
+ start = fmw->data + offset;
+ remaining = fmw->size - offset;
+ nul = memchr(start, '\0', remaining);
+ if (!nul)
+ return -EINVAL;
+
+ len = nul - start;
+ if (len > INT_MAX)
+ return -EOVERFLOW;
+
+ return len;
+}
+
static int fw_parse_variable_hdr(struct tasdevice_priv
*tas_priv, struct tasdevice_dspfw_hdr *fw_hdr,
const struct firmware *fmw, int offset)
{
const unsigned char *buf = fmw->data;
- int len = strlen((char *)&buf[offset]);
+ int len;
+ len = tasdevice_fw_strnlen(fmw, offset);
+ if (len < 0) {
+ dev_err(tas_priv->dev, "%s: Description error\n", __func__);
+ offset = len;
+ goto out;
+ }
len++;
if (offset + len + 8 > fmw->size) {
memcpy(img_data->name, &data[offset], 64);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
+ offset = n;
+ goto out;
+ }
n++;
if (offset + n + 2 > fmw->size) {
dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
}
offset += 64;
- n = strlen((char *)&buf[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
/* skip '\0' and 5 unused bytes */
n += 6;
if (offset + n > fmw->size) {
memcpy(config->name, &data[offset], 64);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
n += 15;
if (offset + n > fmw->size) {
dev_err(tas_priv->dev, "Description err\n");
{
struct tasdevice_calibration *calibration;
unsigned char *data = (unsigned char *)fmw->data;
- unsigned int i, n;
+ unsigned int i;
+ int n;
if (offset + 2 > fmw->size) {
dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__);
calibration = &(tas_fmw->calibrations[i]);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
/* skip '\0' and 2 unused bytes */
n += 3;
if (offset + n > fmw->size) {