Skip to content

Commit ce8e575

Browse files
examples/configdata: exercise unregister/register lifetime
Add a regression test for apache/nuttx#20166 to the configdata example, which runs automatically in every sim:configdata build. After the normal configdata test loops, close the long-lived descriptor and run a full lifetime cycle on /dev/config: - mtdconfig_unregister() must succeed, - the unregistered device must no longer be openable (ENOENT), - the same MTD device must be registerable again and usable, - a final unregister must succeed, leaving the device unregistered. Before the driver fix this crashes deterministically: the old mtdconfig_unregister_by_path() freed the private device structure before closing its temporary file, so the subsequent open() faults in mm_malloc on the corrupted heap (SIGSEGV observed on sim right after unregister returns). With the fix the whole example, 934706/934706 checks included, completes cleanly. The test uses only generic configdata APIs, so it also passes unchanged under CONFIG_MTD_CONFIG_NVS, whose open/close callbacks are no-ops. Assisted-by: Claude:claude-opus Signed-off-by: Arnav Sharma <2006arnavsharma@gmail.com>
1 parent d1b15db commit ce8e575

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

examples/configdata/configdata_main.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,80 @@ static void configdata_cleardeleted(void)
609609
g_ndeleted = 0;
610610
}
611611

612+
/****************************************************************************
613+
* Name: configdata_testunregister
614+
*
615+
* Description:
616+
* Exercise the /dev/config register/unregister lifetime. Unregister
617+
* the device, verify that it can no longer be opened, then register
618+
* it again and verify that it is usable. This is a regression test:
619+
* freeing the private device structure before the temporary file used
620+
* during unregister is closed corrupts the heap and crashes the open
621+
* below.
622+
*
623+
* Input Parameters:
624+
* mtd - Pointer to the MTD device bound to the /dev/config device
625+
*
626+
****************************************************************************/
627+
628+
static void configdata_testunregister(FAR struct mtd_dev_s *mtd)
629+
{
630+
int fd;
631+
int ret;
632+
633+
close(g_fd);
634+
g_fd = -1;
635+
636+
ret = mtdconfig_unregister();
637+
if (ret < 0)
638+
{
639+
printf("ERROR: /dev/config unregistration failed: %d\n", ret);
640+
fflush(stdout);
641+
exit(3);
642+
}
643+
644+
fd = open("/dev/config", O_RDONLY);
645+
if (fd >= 0 || errno != ENOENT)
646+
{
647+
printf("ERROR: /dev/config still accessible after unregister: "
648+
"fd=%d errno=%d\n", fd, errno);
649+
fflush(stdout);
650+
651+
if (fd >= 0)
652+
{
653+
close(fd);
654+
}
655+
656+
exit(3);
657+
}
658+
659+
ret = mtdconfig_register(mtd);
660+
if (ret < 0)
661+
{
662+
printf("ERROR: /dev/config re-registration failed: %d\n", ret);
663+
fflush(stdout);
664+
exit(3);
665+
}
666+
667+
fd = open("/dev/config", O_RDONLY);
668+
if (fd < 0)
669+
{
670+
printf("ERROR: Failed to re-open /dev/config %d\n", errno);
671+
fflush(stdout);
672+
exit(3);
673+
}
674+
675+
close(fd);
676+
677+
ret = mtdconfig_unregister();
678+
if (ret < 0)
679+
{
680+
printf("ERROR: /dev/config final unregistration failed: %d\n", ret);
681+
fflush(stdout);
682+
exit(3);
683+
}
684+
}
685+
612686
/****************************************************************************
613687
* Public Functions
614688
****************************************************************************/
@@ -786,6 +860,8 @@ int main(int argc, FAR char *argv[])
786860
configdata_delallfiles();
787861
#endif
788862

863+
configdata_testunregister(mtd);
864+
789865
configdata_endmemusage();
790866
fflush(stdout);
791867
return 0;

0 commit comments

Comments
 (0)