php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #54173 After you write IPTC several times in the same JPEG file, the file is corrupted
Submitted: 2011-03-06 11:27 UTC Modified: 2015-07-26 04:22 UTC
Votes:9
Avg. Score:4.6 ± 0.8
Reproduced:7 of 7 (100.0%)
Same Version:2 (28.6%)
Same OS:0 (0.0%)
From: axelgauffre at gmail dot com Assigned: cmb (profile)
Status: No Feedback Package: GD related
PHP Version: 5.3.5 OS: Vista 64
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2011-03-06 11:27 UTC] axelgauffre at gmail dot com
Description:
------------
Sometimes writing IPTC in a JPEG file seems to corrupt it.
This behaviour happens after you write several times in the same file (after 10 to 
20 times or so...).

The consequence is that the next call to GetImageSize on this file will fail.

I don't know if the problem comes from iptcembed or from GetImageSize.


I am using Wampserver 2 with PHP 5.3.0 on Vista 64.

Test script:
---------------
<?php
$file_path_and_name="020SC_BF0196D001_M.jpg";
$iptc_field_to_modify="2#005";

//Read IPTC from file
if (!GetImageSize($file_path_and_name, $getimagesize_result))
{
	echo("GetImageSize error<br />");
	die();
}

//Handle return from GetImageSize
if (!isset($getimagesize_result["APP13"]))
	$iptc_array=array();
else
{
	//Get APP13
	$iptcparse_result=iptcparse($getimagesize_result["APP13"]);
	if ($iptcparse_result===false)
	{
		echo("iptcparse error<br />");
		die();
	}

	//Handle iptcparse result
	$iptc_array=array();
	foreach ($iptcparse_result as $iptcparse_index => &$iptcparse_value)
	{
		$iptc_array[$iptcparse_index]="";
		for($i=0;$i<count($iptcparse_value);$i++)
			$iptc_array[$iptcparse_index].=($i<count($iptcparse_value)-1)?$iptcparse_value[$i].",":$iptcparse_value[$i];
	}
}

//foreach($iptc_array as $index => $value)
//	echo($index."  ".$value."<br />");
if (isset($iptc_array["2#005"]))
	echo($iptc_array["2#005"]."<br />");

//Modify the value in the IPTC array
$iptc_array[$iptc_field_to_modify]=rand (1, 1000);
	
//Transform the the IPTC array into a string to be used by iptcembed
$string_for_iptcembed="";
foreach($iptc_array as $iptc_array_index => &$iptc_array_value)
{
	 $iptc_array_index=substr($iptc_array_index, 2);
	 
	 $length = strlen($iptc_array_value);
   $retval = chr(0x1C).chr(2).chr($iptc_array_index);

   if($length < 0x8000)
      $retval .= chr($length >> 8).chr($length& 0xFF);
   else{
      $retval .= chr(0x80).chr(0x04). 
                 chr(($length >> 24)& 0xFF). 
                 chr(($length >> 16)& 0xFF). 
                 chr(($length >> 8)& 0xFF). 
                 chr($length& 0xFF);
   }
   $string_for_iptcembed.=$retval.$iptc_array_value;	 
}

//Call to iptcembed
$binary_data=iptcembed($string_for_iptcembed, $file_path_and_name);
if ($binary_data===false)
{
	echo("iptcembed error<br />");
	die();
}

//TODO ??? It doesn't solve the problem anyway...
//@unlink($file_path_and_name);//delete if exists

//Open file for writing
if (DIRECTORY_SEPARATOR=="/")
	$file = fopen($file_path_and_name, "w");//linux
else if (DIRECTORY_SEPARATOR=="\\")
	$file = fopen($file_path_and_name, "wb");//windows
if(!$file)
{
	echo("fopen error<br />");
	die();
}

//Writing
if (false===fwrite($file, $binary_data))
{
	echo("fwrite error<br />");
	
	if(fclose($file)===false)
		echo("fclose error<br />");
	die();
}
	
//Close file
if(fclose($file)===false)
{
	echo("fclose error<br />");
	die();
}
	
//Let's check that everything went fine:
//Sometimes writing IPTC in a JPEG file seems to corrupt it.
//This behaviour happens after you write several times in the same file (after 10 to 20 times or so...).
//The only solution I found to fix the problem: create a new file with imagecreatefromjpeg. But this has 2 main inconvenients:
//	- it takes long (3 to 4 seconds with a high res file)
//	- you loose every other metadata: XMP, EXIF...
if(false===GetImageSize($file_path_and_name, $bogus))
{
	echo("!!!!!!!!!!!!!!!!!!!!!! GetImageSize error !!!!!!!!!!!!!!!!!!!!!!!!!!!<br />");
	
	$image = imagecreatefromjpeg($file_path_and_name);
	if ($image===false)
	{
		echo("imagecreatefromjpeg error<br />");
		die();
	}
	if (false===imagejpeg($image, $file_path_and_name))
	{
		echo("imagejpeg error<br />");
		die();
	}
}
?>

Expected result:
----------------
Each call should do exactly the same as the previous one : read and write IPTC 
metadata.

Actual result:
--------------
After several times, GetImageSize returns false.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-07-18 00:11 UTC] cmb@php.net
-Summary: After you write IPTC several times in the same JPEG file, the file is corrupted +Summary: Repeated iptcembed() corrupts JPEG file -Status: Open +Status: Verified -Operating System: Vista 64 +Operating System: * -PHP Version: 5.3.5 +PHP Version: 5.6.11 -Assigned To: +Assigned To: cmb
 [2015-07-18 00:11 UTC] cmb@php.net
Confirmed.
 [2015-07-18 00:11 UTC] cmb@php.net
Confirmed.
 [2015-07-18 19:14 UTC] cmb@php.net
-Summary: Repeated iptcembed() corrupts JPEG file +Summary: After you write IPTC several times in the same JPEG file, the file is corrupted -Status: Verified +Status: Feedback -Operating System: * +Operating System: Vista 64 -PHP Version: 5.6.11 +PHP Version: 5.3.5
 [2015-07-18 19:14 UTC] cmb@php.net
Well, actually I can't confirm this very issue. I'd need
020SC_BF0196D001_M.jpg or some other image that shows this
behavior. Could you please supply a download link to such an
image?

What I can confirm is that there is a superfluous byte added on
repeat calls to iptcembed(), which I reported as bug #70096.
 [2015-07-26 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Tue Feb 25 06:01:25 2020 UTC