summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2024-03-26 19:02:09 -0400
committerWilliam Wilgus <me.theuser@yahoo.com>2024-03-29 10:27:03 -0400
commit52e22b253d7b7d2419a9fb22e2f40c5aeeaa821d (patch)
tree2869286de851e0a7affd2b7061a1b93cb2fb4710
parent19f21a2b3f75b38d313a3d9a1f87a537211c0204 (diff)
downloadrockbox-52e22b253d7b7d2419a9fb22e2f40c5aeeaa821d.tar.gz
rockbox-52e22b253d7b7d2419a9fb22e2f40c5aeeaa821d.zip
[Bugfix] ft_assemble_path extra slashes, Volume unmound double free
Change-Id: Ie2e7702d8e252ce29af0b9dbd2e8d9e892b9ca18
-rw-r--r--apps/filetree.c58
-rw-r--r--firmware/common/rb_namespace.c19
-rw-r--r--firmware/include/dircache_redirect.h5
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
478int ft_assemble_path(char *buf, size_t bufsz, const char* currdir, const char* filename) 478int 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
517int ft_enter(struct tree_context* c) 522int 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
140static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) 140static 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))