This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 209f73ff0e1a03ccad2589e014b263976892338c Author: Marco Casaroli <[email protected]> AuthorDate: Fri Jul 31 14:18:32 2026 +0200 drivers/power: Do not call gauge methods a driver did not implement. Every BATIOC_* case in the gauge upper half calls dev->ops->X() after checking only that the *argument* pointer is non-NULL. The operations themselves are optional -- max1704x.c implements four of the eight, and the in-tree fake gauge leaves chipid and operate NULL -- so asking a gauge for something it does not provide calls through a NULL pointer. On ARM that is not a null dereference but a branch to address 0, which has the Thumb bit clear: the core takes a usage fault with CFSR bit 17, INVSTATE, escalated to a hard fault. From userspace it looks like the program stopped mid-run for no reason, and on a board whose assert path delays before resetting it looks like a hang. Guard all eight. A missing method is now ENOTTY, which is what the default case already returns for an unrecognised command and what a caller can sensibly probe for. Tested on sim:nsh with the fake gauge and a local test app. Before the change, ioctl(BATIOC_CHIPID) kills the simulator with SIGSEGV. After the change, BATIOC_CHIPID and BATIOC_OPERATE return ENOTTY and BATIOC_VOLTAGE still returns the voltage. nucleo-f412zg:nsh with BATTERY_GAUGE, MAX1704X, BQ27426 and BATTERY_FAKE_GAUGE builds. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- drivers/power/battery/battery_gauge.c | 96 +++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 16 deletions(-) diff --git a/drivers/power/battery/battery_gauge.c b/drivers/power/battery/battery_gauge.c index 101cca01c66..fbd52a293db 100644 --- a/drivers/power/battery/battery_gauge.c +++ b/drivers/power/battery/battery_gauge.c @@ -313,10 +313,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR int *ptr = (FAR int *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->state(dev, ptr); + break; } + + if (dev->ops->state == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->state(dev, ptr); } break; @@ -324,10 +332,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR bool *ptr = (FAR bool *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->online(dev, ptr); + break; } + + if (dev->ops->online == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->online(dev, ptr); } break; @@ -335,10 +351,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR int *ptr = (FAR int *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->voltage(dev, ptr); + break; } + + if (dev->ops->voltage == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->voltage(dev, ptr); } break; @@ -346,10 +370,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR int *ptr = (FAR int *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->capacity(dev, ptr); + break; } + + if (dev->ops->capacity == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->capacity(dev, ptr); } break; @@ -357,10 +389,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR int *ptr = (FAR int *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->current(dev, ptr); + break; } + + if (dev->ops->current == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->current(dev, ptr); } break; @@ -368,10 +408,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR int *ptr = (FAR int *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->temp(dev, ptr); + break; } + + if (dev->ops->temp == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->temp(dev, ptr); } break; @@ -379,10 +427,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR unsigned int *ptr = (FAR unsigned int *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->chipid(dev, ptr); + break; } + + if (dev->ops->chipid == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->chipid(dev, ptr); } break; @@ -390,10 +446,18 @@ static int bat_gauge_ioctl(FAR struct file *filep, { FAR int *ptr = (FAR int *)((uintptr_t)arg); - if (ptr) + if (ptr == NULL) { - ret = dev->ops->operate(dev, ptr); + break; } + + if (dev->ops->operate == NULL) + { + ret = -ENOTTY; + break; + } + + ret = dev->ops->operate(dev, ptr); } break;
