@@ -106,6 +106,31 @@ public static (uint rootDirSector, uint rootDirSize, long discLseek) VerifyXiso(
106106 throw new ExtractErrorException ( ExtractError . ErrIsoNoFiles ) ;
107107 }
108108
109+ var fileLength = fs . Length ;
110+ var totalSectors = ( uint ) ( fileLength / Constants . SectorSize ) ;
111+
112+ if ( rootDirSector >= totalSectors )
113+ {
114+ Logger . LogErr ( $ "{ isoName } : root directory sector { rootDirSector } exceeds total sectors { totalSectors } \n ") ;
115+ throw new InvalidDataException (
116+ $ "Corrupt XISO: { isoName } — root directory sector { rootDirSector } is beyond end of image ({ totalSectors } sectors).") ;
117+ }
118+
119+ if ( rootDirSize == 0 )
120+ {
121+ Logger . LogErr ( $ "{ isoName } : root directory size is zero but sector is non-zero\n ") ;
122+ throw new InvalidDataException (
123+ $ "Corrupt XISO: { isoName } — root directory size is zero with non-zero sector pointer.") ;
124+ }
125+
126+ var availableBytes = ( long ) ( totalSectors - rootDirSector ) * Constants . SectorSize ;
127+ if ( rootDirSize > availableBytes )
128+ {
129+ Logger . LogErr ( $ "{ isoName } : root directory size { rootDirSize } exceeds available space { availableBytes } \n ") ;
130+ throw new InvalidDataException (
131+ $ "Corrupt XISO: { isoName } — root directory size { rootDirSize } bytes exceeds available space ({ availableBytes } bytes from sector { rootDirSector } ).") ;
132+ }
133+
109134 fs . Seek ( ( long ) rootDirSector * Constants . SectorSize + discLseek , SeekOrigin . Begin ) ;
110135
111136 return ( rootDirSector , rootDirSize , discLseek ) ;
@@ -192,7 +217,7 @@ internal static int TraverseXiso(
192217
193218 var nameBuf = new byte [ filenameLength ] ;
194219 ReadExact ( fs , nameBuf ) ;
195- var filename = Encoding . ASCII . GetString ( nameBuf ) ;
220+ var filename = Latin1Encoding . Instance . GetString ( nameBuf ) ;
196221
197222 if ( string . Equals ( filename , "." , StringComparison . Ordinal ) || string . Equals ( filename , ".." , StringComparison . Ordinal ) ||
198223 filename . Contains ( '/' ) || filename . Contains ( '\\ ' ) )
@@ -217,11 +242,18 @@ internal static int TraverseXiso(
217242 {
218243 llCompat = false ;
219244
245+ var leftSeek = dirStart + ( long ) lOffset * Constants . DwordSize ;
246+ if ( leftSeek >= fs . Length )
247+ {
248+ Logger . LogErr ( $ "warning: left offset { lOffset } (seek { leftSeek } ) exceeds file length { fs . Length } , truncating directory.\n ") ;
249+ goto end_traverse ;
250+ }
251+
220252 var left = new DirEntry ( ) ;
221253 dir . Left = left ;
222254 left . Parent = dir ;
223255
224- fs . Seek ( dirStart + ( long ) lOffset * Constants . DwordSize , SeekOrigin . Begin ) ;
256+ fs . Seek ( leftSeek , SeekOrigin . Begin ) ;
225257
226258 var savedDir = dir . Left ! ;
227259 TraverseXiso ( fs , savedDir , dirStart , path , mode , ref avlRoot , llCompat , discLseek ) ;
@@ -316,7 +348,14 @@ internal static int TraverseXiso(
316348 }
317349 }
318350
319- fs . Seek ( dirStart + ( long ) rOffset * Constants . DwordSize , SeekOrigin . Begin ) ;
351+ var rightSeek = dirStart + ( long ) rOffset * Constants . DwordSize ;
352+ if ( rightSeek >= fs . Length )
353+ {
354+ Logger . LogErr ( $ "warning: right offset { rOffset } (seek { rightSeek } ) exceeds file length { fs . Length } , truncating directory.\n ") ;
355+ break ;
356+ }
357+
358+ fs . Seek ( rightSeek , SeekOrigin . Begin ) ;
320359
321360 dir . Filename = "" ;
322361 lOffset = rOffset ;
@@ -527,8 +566,21 @@ public static int DecodeXiso(
527566 if ( mode == ExtractMode . Extract && outputPath != null )
528567 {
529568 cwd = Directory . GetCurrentDirectory ( ) ;
530- Directory . CreateDirectory ( outputPath ) ;
531- Directory . SetCurrentDirectory ( outputPath ) ;
569+ try
570+ {
571+ Directory . CreateDirectory ( outputPath ) ;
572+ Directory . SetCurrentDirectory ( outputPath ) ;
573+ }
574+ catch ( UnauthorizedAccessException ex )
575+ {
576+ Logger . LogErr ( $ "Error: permission denied: { outputPath } \n ") ;
577+ throw new IOException ( $ "Permission denied: { outputPath } ", ex ) ;
578+ }
579+ catch ( IOException ex )
580+ {
581+ Logger . LogErr ( $ "Error: cannot access output directory: { outputPath } : { ex . Message } \n ") ;
582+ throw ;
583+ }
532584 }
533585
534586 using var fs = new FileStream (
@@ -553,8 +605,21 @@ public static int DecodeXiso(
553605
554606 if ( mode == ExtractMode . Extract && outputPath == null )
555607 {
556- Directory . CreateDirectory ( isoName ) ;
557- Directory . SetCurrentDirectory ( isoName ) ;
608+ try
609+ {
610+ Directory . CreateDirectory ( isoName ) ;
611+ Directory . SetCurrentDirectory ( isoName ) ;
612+ }
613+ catch ( UnauthorizedAccessException ex )
614+ {
615+ Logger . LogErr ( $ "Error: permission denied: { isoName } \n ") ;
616+ throw new IOException ( $ "Permission denied: { isoName } ", ex ) ;
617+ }
618+ catch ( IOException ex )
619+ {
620+ Logger . LogErr ( $ "Error: cannot create output directory: { isoName } : { ex . Message } \n ") ;
621+ throw ;
622+ }
558623 }
559624 }
560625
0 commit comments