@@ -1662,37 +1662,45 @@ MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
16621662%
16631663*/
16641664MagickExport size_t InterpretImageFilename (const ImageInfo * image_info ,
1665- Image * image ,const char * format ,int value ,char * filename )
1665+ Image * image ,const char * format ,int value ,char * filename ,
1666+ ExceptionInfo * exception )
16661667{
16671668 char
1668- * q ;
1669+ * p = filename ,
1670+ pattern [MagickPathExtent ];
16691671
16701672 const char
1671- * p ;
1672-
1673- int
1674- c ;
1675-
1676- MagickBooleanType
1677- canonical ;
1673+ * cursor = format ;
16781674
1679- ssize_t
1680- offset ;
1681-
1682- canonical = MagickFalse ;
1683- offset = 0 ;
1684- (void ) CopyMagickString (filename ,format ,MaxTextExtent );
1675+ /*
1676+ Start with a copy of the format string.
1677+ */
1678+ (void ) CopyMagickString (filename ,format ,MagickPathExtent );
16851679 if (IsStringTrue (GetImageOption (image_info ,"filename:literal" )) != MagickFalse )
16861680 return (strlen (filename ));
1687- for ( p = strchr (format ,'%' ); p != (char * ) NULL ; p = strchr ( p + 1 , '%' ) )
1681+ while (( cursor = strchr (cursor ,'%' )) != (const char * ) NULL )
16881682 {
1689- q = (char * ) p + 1 ;
1690- if (* q == '%' )
1683+ const char
1684+ * q = cursor ;
1685+
1686+ ssize_t
1687+ offset = (ssize_t ) (cursor - format );
1688+
1689+ cursor ++ ; /* move past '%' */
1690+ if (* cursor == '%' )
16911691 {
1692- p ++ ;
1692+ /*
1693+ Escaped %%.
1694+ */
1695+ cursor ++ ;
16931696 continue ;
16941697 }
1695- switch (* q )
1698+ /*
1699+ Skip padding digits like %03d.
1700+ */
1701+ if (* cursor == '0' )
1702+ (void ) strtol (cursor ,(char * * ) & cursor ,10 );
1703+ switch (* cursor )
16961704 {
16971705 case 'd' :
16981706 case 'o' :
@@ -1701,94 +1709,62 @@ MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
17011709 ssize_t
17021710 count ;
17031711
1704- q ++ ;
1705- c = (* q );
1706- * q = '\0' ;
1707- count = FormatLocaleString (filename + (p - format - offset ),(size_t )
1708- (MaxTextExtent - (p - format - offset )),p ,value );
1709- if ((count <= 0 ) || (count > (MagickPathExtent - (p - format - offset ))))
1712+ count = FormatLocaleString (pattern ,sizeof (pattern ),q ,value );
1713+ if ((count <= 0 ) || (count >= MagickPathExtent ))
17101714 return (0 );
1711- offset += (ssize_t ) ((q - p )- count );
1712- * q = c ;
1713- (void ) ConcatenateMagickString (filename ,q ,MaxTextExtent );
1714- canonical = MagickTrue ;
1715- if (* (q - 1 ) != '%' )
1716- break ;
1717- p ++ ;
1715+ if ((offset + count ) >= MagickPathExtent )
1716+ return (0 );
1717+ (void ) CopyMagickString (p + offset ,pattern ,(size_t ) (MagickPathExtent -
1718+ offset ));
1719+ cursor ++ ;
17181720 break ;
17191721 }
17201722 case '[' :
17211723 {
1722- char
1723- pattern [MaxTextExtent ];
1724-
17251724 const char
1726- * value ;
1725+ * end = strchr (cursor ,']' ),
1726+ * option = (const char * ) NULL ;
17271727
1728- char
1729- * r ;
1730-
1731- ssize_t
1732- i ;
1733-
1734- ssize_t
1735- depth ;
1728+ size_t
1729+ extent = (size_t ) (end - cursor );
17361730
17371731 /*
1738- Image option.
1732+ Handle %[key:value];
17391733 */
1740- if (strchr ( p , ']' ) == (char * ) NULL )
1734+ if (end == (const char * ) NULL )
17411735 break ;
1742- depth = 1 ;
1743- r = q + 1 ;
1744- for (i = 0 ; (i < (MaxTextExtent - 1L )) && (* r != '\0' ); i ++ )
1745- {
1746- if (* r == '[' )
1747- depth ++ ;
1748- if (* r == ']' )
1749- depth -- ;
1750- if (depth <= 0 )
1751- break ;
1752- pattern [i ]= (* r ++ );
1753- }
1754- pattern [i ]= '\0' ;
1755- if (LocaleNCompare (pattern ,"filename:" ,9 ) != 0 )
1736+ if (extent >= sizeof (pattern ))
17561737 break ;
1757- value = (const char * ) NULL ;
1738+ (void ) CopyMagickString (pattern ,cursor ,extent );
1739+ pattern [extent ]= '\0' ;
17581740 if (image != (Image * ) NULL )
1759- value = GetImageProperty (image ,pattern );
1760- if ((value == (const char * ) NULL ) &&
1761- (image != (Image * ) NULL ))
1762- value = GetImageArtifact (image ,pattern );
1763- if ((value == (const char * ) NULL ) &&
1741+ option = GetImageProperty (image ,pattern ,exception );
1742+ if ((option == (const char * ) NULL ) && (image != (Image * )NULL ))
1743+ option = GetImageArtifact (image ,pattern );
1744+ if ((option == (const char * ) NULL ) &&
17641745 (image_info != (ImageInfo * ) NULL ))
1765- value = GetImageOption (image_info ,pattern );
1766- if (value == (const char * ) NULL )
1767- break ;
1768- q -- ;
1769- c = (* q );
1770- * q = '\0' ;
1771- (void ) CopyMagickString (filename + (p - format - offset ),value ,(size_t )
1772- (MaxTextExtent - (p - format - offset )));
1773- offset += (ssize_t ) strlen (pattern )- (ssize_t ) strlen (value )+ 3 ;
1774- * q = c ;
1775- (void ) ConcatenateMagickString (filename ,r + 1 ,MaxTextExtent );
1776- canonical = MagickTrue ;
1777- if (* (q - 1 ) != '%' )
1746+ option = GetImageOption (image_info ,pattern );
1747+ if (option == (const char * ) NULL )
17781748 break ;
1779- p ++ ;
1749+ (void ) CopyMagickString (p + offset ,option ,(size_t ) (MagickPathExtent -
1750+ offset ));
1751+ cursor = end + 1 ;
17801752 break ;
17811753 }
17821754 default :
17831755 break ;
17841756 }
17851757 }
1786- if (canonical == MagickFalse )
1787- (void ) CopyMagickString (filename ,format ,MaxTextExtent );
1788- else
1789- for (q = filename ; * q != '\0' ; q ++ )
1790- if ((* q == '%' ) && (* (q + 1 ) == '%' ))
1791- (void ) CopyMagickString (q ,q + 1 ,(size_t ) (MaxTextExtent - (q - filename )));
1758+ for (p = filename ; * p != '\0' ; )
1759+ {
1760+ /*
1761+ Replace "%%" with "%".
1762+ */
1763+ if ((* p == '%' ) && (* (p + 1 ) == '%' ))
1764+ (void ) memmove (p ,p + 1 ,strlen (p )); /* shift left */
1765+ else
1766+ p ++ ;
1767+ }
17921768 return (strlen (filename ));
17931769}
17941770
0 commit comments