DF-3124 / fix.diff
diff --git a/sys/vfs/isofs/cd9660/cd9660_vfsops.c b/sys/vfs/isofs/cd9660/cd9660_vfsops.c index 1111111..2222222 100644 --- a/sys/vfs/isofs/cd9660/cd9660_vfsops.c +++ b/sys/vfs/isofs/cd9660/cd9660_vfsops.c @@ -488,13 +488,28 @@ iso_mountfs(struct vnode *devvp, struct mount *mp, struct iso_args *argp) ISOFSMNT_UID | ISOFSMNT_GID); if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) { + /* + * The charset names come from the mount arguments and are + * not guaranteed to be NUL-terminated (ICONV_CSNMAXLEN-1 + * usable bytes); force termination before they are used as + * C strings by iconv_open(). + */ bcopy(argp->cs_local, cs_local, sizeof(cs_local)); bcopy(argp->cs_disk, cs_disk, sizeof(cs_disk)); - cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l); - cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d); + cs_local[sizeof(cs_local) - 1] = 0; + cs_disk[sizeof(cs_disk) - 1] = 0; + if (cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l) != 0) + isomp->im_d2l = NULL; + if (cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d) != 0) + isomp->im_l2d = NULL; + if (isomp->im_d2l == NULL || isomp->im_l2d == NULL) { + /* + * The charset pair is unavailable. Fall back to no + * conversion instead of keeping NULL handles that + * isochar()/sgetrune() would pass to convchr() + * (NULL-deref panic on the first lookup/readdir). + */ + if (isomp->im_d2l != NULL) { + cd9660_iconv->close(isomp->im_d2l); + isomp->im_d2l = NULL; + } + if (isomp->im_l2d != NULL) { + cd9660_iconv->close(isomp->im_l2d); + isomp->im_l2d = NULL; + } + isomp->im_flags &= ~ISOFSMNT_KICONV; + } } else { isomp->im_d2l = NULL; isomp->im_l2d = NULL; |