diff options
author | William Wilgus <wilgus.william@gmail.com> | 2024-03-26 19:02:09 -0400 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2024-03-29 10:27:03 -0400 |
commit | 52e22b253d7b7d2419a9fb22e2f40c5aeeaa821d (patch) | |
tree | 2869286de851e0a7affd2b7061a1b93cb2fb4710 | |
parent | 19f21a2b3f75b38d313a3d9a1f87a537211c0204 (diff) | |
download | rockbox-52e22b253d7b7d2419a9fb22e2f40c5aeeaa821d.tar.gz rockbox-52e22b253d7b7d2419a9fb22e2f40c5aeeaa821d.zip |
[Bugfix] ft_assemble_path extra slashes, Volume unmound double free
Change-Id: Ie2e7702d8e252ce29af0b9dbd2e8d9e892b9ca18
-rw-r--r-- | apps/filetree.c | 58 | ||||
-rw-r--r-- | firmware/common/rb_namespace.c | 19 | ||||
-rw-r--r-- | firmware/include/dircache_redirect.h | 5 |
3 files changed, 54 insertions, 28 deletions
diff --git a/apps/filetree.c b/apps/filetree.c index 4f59804686..66b5c843ca 100644 --- a/apps/filetree.c +++ b/apps/filetree.c | |||
@@ -477,41 +477,46 @@ static void ft_apply_skin_file(char *buf, char *file, const int maxlen) | |||
477 | 477 | ||
478 | int ft_assemble_path(char *buf, size_t bufsz, const char* currdir, const char* filename) | 478 | int ft_assemble_path(char *buf, size_t bufsz, const char* currdir, const char* filename) |
479 | { | 479 | { |
480 | int len; | 480 | size_t len; |
481 | if (!filename) | 481 | if (!filename) |
482 | filename = ""; | 482 | filename = ""; |
483 | |||
483 | #ifdef HAVE_MULTIVOLUME | 484 | #ifdef HAVE_MULTIVOLUME |
484 | if (currdir && currdir[0] && currdir[1]) /* Not in / */ | 485 | if (currdir && currdir[0] && currdir[1]) /* Not in / */ |
485 | { | 486 | { |
486 | if (currdir[1] != VOL_START_TOK) | 487 | if (currdir[1] != VOL_START_TOK) |
487 | { | 488 | { |
488 | len = snprintf(buf, bufsz, "%s%s/%s", root_realpath(), currdir, filename); | 489 | len = path_append(buf, root_realpath(), currdir, bufsz); |
490 | if (len < bufsz) | ||
491 | len = path_append(buf, buf + len, filename, bufsz - len); | ||
489 | } | 492 | } |
490 | else | 493 | len = path_append(buf, currdir, filename, bufsz); |
491 | len = snprintf(buf, bufsz, "%s/%s", currdir, filename); | ||
492 | } | 494 | } |
493 | else /* In / */ | 495 | else /* In / */ |
494 | { | 496 | { |
495 | if (filename[0] != VOL_START_TOK) | 497 | if (filename[0] != VOL_START_TOK) |
496 | { | 498 | { |
497 | len = snprintf(buf, bufsz, "%s/%s",root_realpath(), filename); | 499 | len = path_append(buf, root_realpath(), filename, bufsz); |
498 | } | 500 | } |
499 | else | 501 | else |
500 | len = snprintf(buf, bufsz, "/%s", filename); | 502 | len = path_append(buf, PATH_SEPSTR, filename, bufsz); |
501 | } | 503 | } |
502 | #else | 504 | #else |
503 | if (currdir && currdir[0] && currdir[1]) /* Not in / */ | 505 | if (currdir && currdir[0] && currdir[1]) /* Not in / */ |
504 | { | 506 | { |
505 | len = snprintf(buf, bufsz, "%s%s/%s", root_realpath(), currdir, filename); | 507 | len = path_append(buf, root_realpath(), currdir, bufsz); |
508 | if(len < bufsz) | ||
509 | len = path_append(buf, buf + len, filename, bufsz - len); | ||
506 | } | 510 | } |
507 | else /* In / */ | 511 | else /* In / */ |
508 | { | 512 | { |
509 | len = snprintf(buf, bufsz, "%s/%s",root_realpath(), filename); | 513 | len = path_append(buf, root_realpath(), filename, bufsz); |
510 | } | 514 | } |
511 | #endif | 515 | #endif |
512 | if ((unsigned) len > bufsz) | 516 | |
517 | if (len > bufsz) | ||
513 | splash(HZ, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); | 518 | splash(HZ, ID2P(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); |
514 | return len; | 519 | return (int)len; |
515 | } | 520 | } |
516 | 521 | ||
517 | int ft_enter(struct tree_context* c) | 522 | int ft_enter(struct tree_context* c) |
@@ -528,7 +533,6 @@ int ft_enter(struct tree_context* c) | |||
528 | 533 | ||
529 | int file_attr = file->attr; | 534 | int file_attr = file->attr; |
530 | ft_assemble_path(buf, sizeof(buf), c->currdir, file->name); | 535 | ft_assemble_path(buf, sizeof(buf), c->currdir, file->name); |
531 | |||
532 | if (file_attr & ATTR_DIRECTORY) { | 536 | if (file_attr & ATTR_DIRECTORY) { |
533 | memcpy(c->currdir, buf, sizeof(c->currdir)); | 537 | memcpy(c->currdir, buf, sizeof(c->currdir)); |
534 | if ( c->dirlevel < MAX_DIR_LEVELS ) | 538 | if ( c->dirlevel < MAX_DIR_LEVELS ) |
@@ -814,17 +818,39 @@ int ft_exit(struct tree_context* c) | |||
814 | extern char lastfile[]; /* from tree.c */ | 818 | extern char lastfile[]; /* from tree.c */ |
815 | char buf[MAX_PATH]; | 819 | char buf[MAX_PATH]; |
816 | int rc = 0; | 820 | int rc = 0; |
817 | bool exit_func = false; | 821 | bool exit_func = false; |
818 | |||
819 | int i = strlen(c->currdir); | 822 | int i = strlen(c->currdir); |
820 | if (i>1) { | 823 | if (i>1) { |
821 | while (c->currdir[i-1]!='/') | 824 | while (c->currdir[i-1]!=PATH_SEPCH) |
822 | i--; | 825 | i--; |
823 | strcpy(buf,&c->currdir[i]); | 826 | strcpy(buf,&c->currdir[i]); |
824 | if (i==1) | 827 | if (i==1) |
825 | c->currdir[i]=0; | 828 | c->currdir[i]='\0'; |
826 | else | 829 | else |
827 | c->currdir[i-1]=0; | 830 | c->currdir[i-1]='\0'; |
831 | |||
832 | #ifdef HAVE_MULTIVOLUME /* un-redirect the realpath */ | ||
833 | if ((unsigned)c->dirlevel<=2) /* only expect redirect two levels max */ | ||
834 | { | ||
835 | char *currdir = c->currdir; | ||
836 | const char *root = root_realpath(); | ||
837 | int len = i-1; | ||
838 | /* compare to the root path bail if they don't match except single '/' */ | ||
839 | for (; len > 0 && *root != '\0' && *root == *currdir; len--) | ||
840 | { | ||
841 | root++; | ||
842 | currdir++; | ||
843 | } | ||
844 | if (*root == PATH_SEPCH) /* root may have trailing slash */ | ||
845 | root++; | ||
846 | if (*root == '\0' && | ||
847 | (len == 0 || (len == 1 && *currdir == PATH_SEPCH))) | ||
848 | { | ||
849 | strcpy(c->currdir, PATH_ROOTSTR); | ||
850 | c->dirlevel=1; | ||
851 | } | ||
852 | } | ||
853 | #endif | ||
828 | 854 | ||
829 | if (*c->dirfilter > NUM_FILTER_MODES && c->dirlevel < 1) | 855 | if (*c->dirfilter > NUM_FILTER_MODES && c->dirlevel < 1) |
830 | exit_func = true; | 856 | exit_func = true; |
diff --git a/firmware/common/rb_namespace.c b/firmware/common/rb_namespace.c index 85f647c474..5069a8681e 100644 --- a/firmware/common/rb_namespace.c +++ b/firmware/common/rb_namespace.c | |||
@@ -74,7 +74,7 @@ static void unmount_item(int item) | |||
74 | if (!state) | 74 | if (!state) |
75 | return; | 75 | return; |
76 | 76 | ||
77 | if (state & NSITEM_CONTENTS) | 77 | if (item == ROOT_CONTENTS_INDEX && state & NSITEM_CONTENTS) |
78 | { | 78 | { |
79 | fileobj_unmount(root_bindp); | 79 | fileobj_unmount(root_bindp); |
80 | root_bindp = NULL; | 80 | root_bindp = NULL; |
@@ -139,18 +139,19 @@ int root_mount_path(const char *path, unsigned int flags) | |||
139 | int root_state = NSITEM_MOUNTED | (flags & (NSITEM_HIDDEN|NSITEM_CONTENTS)); | 139 | int root_state = NSITEM_MOUNTED | (flags & (NSITEM_HIDDEN|NSITEM_CONTENTS)); |
140 | set_root_item_state(ROOT_CONTENTS_INDEX, root_state); | 140 | set_root_item_state(ROOT_CONTENTS_INDEX, root_state); |
141 | flags |= state; /* preserve the state of the mounted volume */ | 141 | flags |= state; /* preserve the state of the mounted volume */ |
142 | if (!folder) | 142 | |
143 | { | 143 | if (folder) |
144 | folder = ""; | ||
145 | } | ||
146 | else | ||
147 | { | 144 | { |
145 | while (*folder == PATH_SEPCH) | ||
146 | folder++; | ||
148 | /*if a folder has been enumerated don't mark the whole volume */ | 147 | /*if a folder has been enumerated don't mark the whole volume */ |
149 | if (folder[0] != '\0' && folder[1] != '\0') | 148 | if (folder[0] != '\0') |
150 | flags &= ~NSITEM_CONTENTS; | 149 | flags &= ~NSITEM_CONTENTS; |
151 | 150 | else | |
151 | folder = NULL; /*Ensure separator is added by path_append */ | ||
152 | } | 152 | } |
153 | snprintf(root_realpath_internal(), ROOT_MAX_REALPATH,"%s%s", volname, folder); | 153 | |
154 | path_append(root_realpath_internal(), volname, folder, ROOT_MAX_REALPATH); | ||
154 | } | 155 | } |
155 | else if (state) /* error volume already mounted */ | 156 | else if (state) /* error volume already mounted */ |
156 | return -EBUSY; | 157 | return -EBUSY; |
diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h index 36f68b7251..f51ce70690 100644 --- a/firmware/include/dircache_redirect.h +++ b/firmware/include/dircache_redirect.h | |||
@@ -139,10 +139,8 @@ static inline void fileop_onsync_internal(struct filestr_base *stream) | |||
139 | 139 | ||
140 | static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) | 140 | static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) |
141 | { | 141 | { |
142 | #if (defined(HAVE_MULTIVOLUME) || (defined(HAVE_MULTIBOOT) && !defined(BOOTLOADER))) | ||
143 | char path[VOL_MAX_LEN+2]; | ||
144 | #endif | ||
145 | #if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) | 142 | #if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) |
143 | char path[VOL_MAX_LEN+2]; | ||
146 | char rtpath[MAX_PATH / 2]; | 144 | char rtpath[MAX_PATH / 2]; |
147 | make_volume_root(volume, path); | 145 | make_volume_root(volume, path); |
148 | 146 | ||
@@ -185,6 +183,7 @@ standard_redirect: | |||
185 | root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); | 183 | root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); |
186 | } | 184 | } |
187 | #elif defined(HAVE_MULTIVOLUME) | 185 | #elif defined(HAVE_MULTIVOLUME) |
186 | char path[VOL_MAX_LEN+2]; | ||
188 | make_volume_root(volume, path); | 187 | make_volume_root(volume, path); |
189 | root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); | 188 | root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); |
190 | if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) | 189 | if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) |