CVE-2024-32489 (PHP, published 2024-04-15T06:15Z)
Description: value: TCPDF before 6.7.4 mishandles calls that use HTML syntax.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/tecnickcom/TCPDF
Files changed:
CHANGELOG.TXT
LICENSE.TXT
README.md
VERSION
config/tcpdf_config.php
examples/config/tcpdf_config_alt.php
examples/example_049.php
examples/example_066.php
include/barcodes/qrcode.php
include/tcpdf_fonts.php
include/tcpdf_static.php
phpstan.neon.dist
tcpdf.php
tcpdf_autoconfig.php
tcpdf_barcodes_1d.php
tests/composer.json
Commit message: Squash multiple fixes


Vulnerable code:
  2002-2022 Nicola Asuni - Tecnick.com LTD
* **copyright**   2002-2022 Nicola Asuni - Tecnick.com LTD
## IMPORTANT
A new version of this library is under development at https://github.com/tecnickcom/tc-lib-pdf and as a consequence this version will not receive any additional development or support.
This version should be considered obsolete, new projects should use the new version as soon it will become stable.
6.6.2
// Last Update : 2014-12-10
If you are printing user-generated content, tcpdf tag can be unsafe.
You can disable this tag by setting to false the K_TCPDF_CALLS_IN_HTML
constant on TCPDF configuration file.
For security reasons, the parameters for the 'params' attribute of TCPDF
<span style="color:red;">If you are using user-generated content, the tcpdf tag can be unsafe.<br />
You can disable this tag by setting to false the <b>K_TCPDF_CALLS_IN_HTML</b> constant on TCPDF configuration file.</span>
$params = $pdf->serializeTCPDFtagParameters(array('CODE 39', 'C39', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf method="write1DBarcode" params="'.$params.'" />';
$params = $pdf->serializeTCPDFtagParameters(array('CODE 128', 'C128', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf method="write1DBarcode" params="'.$params.'" />';
$html .= '<tcpdf method="AddPage" /><h2>Graphic Functions</h2>';
$params = $pdf->serializeTCPDFtagParameters(array(0));
$html .= '<tcpdf method="SetDrawColor" params="'.$params.'" />';
$params = $pdf->serializeTCPDFtagParameters(array(50, 50, 40, 10, 'DF', array(), array(0,128,255)));
$html .= '<tcpdf method="Rect" params="'.$params.'" />';
// Load the autoloader, move one folder back from examples
require_once __DIR__ . '/../vendor/autoload.php';
				$pad = 4 - ($table[$tag]['length'] % 4);
				if ($pad != 4) {
					// the length of a table must be a multiple of four bytes
					$table[$tag]['length'] += $pad;
					$table[$tag]['data'] .= str_repeat("\x0", $pad);
				}
				//$table[$tag]['checkSum'] = self::_getTTFtableChecksum($table[$tag]['data'], $table[$tag]['length']);
		$pad = 4 - ($table['loca']['length'] % 4);
		if ($pad != 4) {
			// the length of a table must be a multiple of four bytes
			$table['loca']['length'] += $pad;
			$table['loca']['data'] .= str_repeat("\x0", $pad);
		}
		$table['loca']['checkSum'] = self::_getTTFtableChecksum($table['loca']['data'], $table['loca']['length']);
		$pad = 4 - ($table['glyf']['length'] % 4);
		if ($pad != 4) {
			// the length of a table must be a multiple of four bytes
			$table['glyf']['length'] += $pad;
			$table['glyf']['data'] .= str_repeat("\x0", $pad);
		}
		$table['glyf']['checkSum'] = self::_getTTFtableChecksum($table['glyf']['data'], $table['glyf']['length']);
		$font = substr($font, 0, $table['head']['offset'] + 8).pack('N', $checkSumAdjustment).substr($font, $table['head']['offset'] + 12);
			return array_map(array('TCPDF_FONTS', 'unichrUnicode'), $ta);
		return array_map(array('TCPDF_FONTS', 'unichrASCII'), $ta);
			$carr = array_map(array('TCPDF_FONTS', 'uniord'), $chars);
// Last Update : 2022-08-12
// Copyright (C) 2002-2022 Nicola Asuni - Tecnick.com LTD
	private static $tcpdf_version = '6.6.2';
			return $ret;
	 * 
        # remove once https://github.com/phpstan/phpstan/issues/7955 is fixed
        - fonts/
// Version     : 6.6.2
// Last Update : 2022-12-06
// Copyright (C) 2002-2022 Nicola Asuni - Tecnick.com LTD
 * @version 6.6.2
 * @version 6.6.2

		if ($padding) {
	 * @param int $hm distance in user units
	 * @param int $fm distance in user units
		if (!isset($name) OR empty($name)) {
		if (isset($diff) AND (!empty($diff))) {
		$maxchwidth = max($chrw);
			$font = $this->getFontBuffer('helvetica');
		$key = 0;
		// create an array of elements
		$dom = array();
		$dom[$key] = array();
		// set inheritable properties fot the first void element
		// possible inheritable properties are: azimuth, border-collapse, border-spacing, caption-side, color, cursor, direction, empty-cells, font, font-family, font-stretch, font-size, font-size-adjust, font-style, font-variant, font-weight, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, orphans, page, page-break-inside, quotes, speak, speak-header, text-align, text-indent, text-transform, volume, white-space, widows, word-spacing
		$dom[$key]['tag'] = false;
		$dom[$key]['block'] = false;
		$dom[$key]['value'] = '';
		$dom[$key]['parent'] = 0;
		$dom[$key]['hide'] = false;
		$dom[$key]['fontname'] = $this->FontFamily;
		$dom[$key]['fontstyle'] = $this->FontStyle;
		$dom[$key]['fontsize'] = $this->FontSizePt;
		$dom[$key]['font-stretch'] = $this->font_stretching;
		$dom[$key]['letter-spacing'] = $this->font_spacing;
		$dom[$key]['stroke'] = $this->textstrokewidth;
		$dom[$key]['fill'] = (($this->textrendermode % 2) == 0);
		$dom[$key]['clip'] = ($this->textrendermode > 3);
		$dom[$key]['line-height'] = $this->cell_height_ratio;
		$dom[$key]['bgcolor'] = false;
		$dom[$key]['fgcolor'] = $this->fgcolor; // color
		$dom[$key]['strokecolor'] = $this->strokecolor;
		$dom[$key]['align'] = '';
		$dom[$key]['listtype'] = '';
		$dom[$key]['text-indent'] = 0;
		$dom[$key]['text-transform'] = '';
		$dom[$key]['border'] = array();
		$dom[$key]['dir'] = $this->rtl?'rtl':'ltr';
		++$key;
	 * Return an hash code used to ensure that the serialized data has been generated by this TCPDF instance.
	 * @param string $data serialized data
	 * @return string
	 * @public static
	protected function getHashForTCPDFtagParams($data) {
		return md5(strlen($data).$this->file_id.$data);
	 * Serialize an array of parameters to be used with TCPDF tag in HTML code.
	 * @param array $data parameters array
	 * @return string containing serialized data
	public function serializeTCPDFtagParameters($data) {
		return $this->getHashForTCPDFtagParams($encoded).$encoded;
	 * Unserialize parameters to be used with TCPDF tag in HTML code.
	protected function unserializeTCPDFtagParameters($data) {
		$hash = substr($data, 0, 32);
		$encoded = substr($data, 32);
		if ($hash != $this->getHashForTCPDFtagParams($encoded)) {
	 * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL language)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul>
Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
					if (isset($tag['attribute']['method'])) {
						$tcpdf_method = $tag['attribute']['method'];
						if (method_exists($this, $tcpdf_method)) {
							if (isset($tag['attribute']['params']) AND (!empty($tag['attribute']['params']))) {
								$params = $this->unserializeTCPDFtagParameters($tag['attribute']['params']);
								call_user_func_array(array($this, $tcpdf_method), $params);
							} else {
								$this->$tcpdf_method();
							}
							$this->newline = true;
		if (isset($this->objcopy)) {
			$objcopy = $this->objcopy;
			$this->_destroy(true, true);
			if ($self) {
				$objvars = get_object_vars($objcopy);
				foreach ($objvars as $key => $value) {
					$this->$key = $value;
				}
				$objcopy->_destroy(true, true);
				/* The unique file_id should not be used during cleanup again */
				$objcopy->file_id = NULL;
				unset($objcopy);
				return $this;
			/* The unique file_id should not be used during cleanup again */
			$this->file_id = NULL;
			return $objcopy;
		return $this;
		if ($stroke < 0) {
		$chr['8'] = '10101110111010';
		$seq = '11011010';
		$seq .= '1101011';
    "keywords": [
        "PDF",
        "tcpdf",
        "test"
    ],
    "license": "LGPL-3.0-only",
        "cs278/mktemp": "*"
    },
    "archive": {
        "exclude": [
            "/examples"
        ]

Fixed code:
6.7.4 (2024-03-24)
	- Upgrade tcpdf tag encryption algorithm.
	- Fix regression issue #699.
	- Fix security issue.
	- [BREAKING CHANGE] The tcpdf HTML tag syntax has changed, see example_049.php.
	- New K_ALLOWED_TCPDF_TAGS configuration constant to set the allowed methods for the tcdpf HTML tag.
	- Raised minimum PHP version to PHP 5.5.0.

6.6.5 (2023-09-02)
	- Fix corrupted file.
	- Fix GitHub automation tests.
	- Fix SPDX license ID (#591)
	- Fix warning "array offset on value of type null" (#620)
	- Improve the README about the status of this library (#589)
	- Fix deprecation warning with PHP 8.1 (#614)
	- Fixes for PHP 8.2 in tcpdf_fonts.php (#632)
	- Fix some php 8+ edge cases (#630)
	- Fix composite glyph output (#581)
	- Fix "access array offset on value of type bool" with PDF/A (#583)
	- Fix non-numeric value warning (#627)
	- Fix issues with S25 barcode (#611)
	- Fix return type annotations (#613)
	- Fix some inconsistencies in type hints (#598)

  2002-2024 Nicola Asuni - Tecnick.com LTD
* **copyright**   2002-2024 Nicola Asuni - Tecnick.com LTD
## NOTE
A new version of this library is under development at https://github.com/tecnickcom/tc-lib-pdf and as a consequence this library is in support only mode.
6.7.4
/**
 * List of TCPDF methods that are allowed to be called using HTML syntax.
 * Note: each method name must end with surrounded with | (pipe) character.
 * The constant K_TCPDF_CALLS_IN_HTML must be set to true.
 * IMPORTANT: For security reason, disable this feature if you are allowing user HTML content.
 */
define('K_ALLOWED_TCPDF_TAGS', '');

/**
 * List of TCPDF methods that are allowed to be called using HTML syntax.
 * Note: each method name must end with surrounded with | (pipe) character.
 * The constant K_TCPDF_CALLS_IN_HTML must be set to true.
 * IMPORTANT: For security reason, disable this feature if you are allowing user HTML content.
 */
define('K_ALLOWED_TCPDF_TAGS', '|AddPage|Rect|SetDrawColor|write1DBarcode|');

// Last Update : 2024-03-18
If you are printing user-generated content, the tcpdf tag should be considered unsafe.
This tag is disabled by default by the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file.
Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code.
For security reasons, the parameters for the 'params' attribute of TCPDF 
<span style="color:red;">If you are using user-generated content, the tcpdf tag should be considered unsafe.<br />
Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code.<br />
This feature is disabled by default by the <b>K_TCPDF_CALLS_IN_HTML</b> constant on TCPDF configuration file.</span>
$data = $pdf->serializeTCPDFtag('write1DBarcode', array('CODE 39', 'C39', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf data="'.$data.'" />';
$data = $pdf->serializeTCPDFtag('write1DBarcode', array('CODE 128', 'C128', '', '', 80, 30, 0.4, array('position'=>'S', 'border'=>true, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>true, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>4), 'N'));
$html .= '<tcpdf data="'.$data.'" />';
$data = $pdf->serializeTCPDFtag('AddPage');
$html .= '<tcpdf data="'.$data.'" /><h2>Graphic Functions</h2>';
$data = $pdf->serializeTCPDFtag('SetDrawColor', array(0));
$html .= '<tcpdf data="'.$data.'" />';
$data = $pdf->serializeTCPDFtag('Rect', array(50, 50, 40, 10, 'DF', array(), array(0,128,255)));
$html .= '<tcpdf data="'.$data.'" />';
// Include the main TCPDF library (search for installation path).
require_once('tcpdf_include.php');
			$row = (int) $row;
				$numPad = ($offset + 3 & ~3) - $offset;
				if($numPad > 0) {
					$table[$tag]['data'] .= str_repeat("\x0", $numPad);
					$offset += $numPad;
				}
				//$table[$tag]['checkSum'] = self::_getTTFtableChecksum($table[$tag]['data'], $table[$tag]['length'] + $numPad);
		$table['loca'] = array();
		$numPad = ($offset + 3 & ~3) - $offset;
		if($numPad > 0) {
			$table['loca']['data'] .= str_repeat("\x0", $numPad);
			$offset += $numPad;
		}
		$table['loca']['checkSum'] = self::_getTTFtableChecksum($table['loca']['data'], $table['loca']['length'] + $numPad);
		$table['glyf'] = array();
		$offset += $table['glyf']['length'];
		$numPad = ($offset + 3 & ~3) - $offset;
		if($numPad > 0) {
			$table['glyf']['data'] .= str_repeat("\x0", $numPad);
			$offset += $numPad;
		}
		$table['glyf']['checkSum'] = self::_getTTFtableChecksum($table['glyf']['data'], $table['glyf']['length'] + $numPad);
		$font = substr($font, 0, $table['head']['offset'] + $offset + 8).pack('N', $checkSumAdjustment).substr($font, $table['head']['offset'] + $offset + 12);
			return array_map(get_called_class().'::unichrUnicode', $ta);
		return array_map(get_called_class().'::unichrASCII', $ta);
			$carr = array_map(get_called_class().'::uniord', $chars);
// Last Update : 2023-09-06
// Copyright (C) 2002-2023 Nicola Asuni - Tecnick.com LTD
	private static $tcpdf_version = '6.7.4';
			return is_array($ret) ? $ret : array();
	 *
// Version     : 6.7.4
// Last Update : 2024-03-18
// Copyright (C) 2002-2024 Nicola Asuni - Tecnick.com LTD
 * @version 6.6.5
 * @version 6.7.4
	 * @var float
	 * @var float
	/**
	 * Internal secret used to encrypt data.
	 * @protected
	 * @since 6.7.4 (2024-03-21)
	 */
	protected $hash_key;

		$this->hash_key = hash_hmac('sha256', TCPDF_STATIC::getRandomSeed($this->file_id), TCPDF_STATIC::getRandomSeed('TCPDF'), false);
		if ($padding && !empty($this->cell_padding)) {
	 * @param float $hm distance in user units
	 * @param float $fm distance in user units
	 * @phpstan-return ($getarray is true ? float[] : float) total string length or array of characted widths
	 * @phpstan-return ($getarray is true ? float[] : float) total string length or array of characted widths
		if (empty($name)) {
		if (!empty($diff)) {
		$maxchwidth = ((is_array($chrw) || $chrw instanceof Countable) && count($chrw) > 0) ? max($chrw) : 0;
			// fallback to avoid division by zero
			$h = $h == 0 ? 1 : $h;
			$font = $this->getFontBuffer((($this->pdfa_mode) ? 'pdfa' : '') .'helvetica');
		// set inheritable properties fot the first void element
		// possible inheritable properties are: azimuth, border-collapse, border-spacing, caption-side, color, cursor, direction, empty-cells, font, font-family, font-stretch, font-size, font-size-adjust, font-style, font-variant, font-weight, letter-spacing, line-height, list-style, list-style-image, list-style-position, list-style-type, orphans, page, page-break-inside, quotes, speak, speak-header, text-align, text-indent, text-transform, volume, white-space, widows, word-spacing
		$dom = array(
			array(
				'tag' => false,
				'block' => false,
				'value' => '',
				'parent' => 0,
				'hide' => false,
				'fontname' => $this->FontFamily,
				'fontstyle' => $this->FontStyle,
				'fontsize' => $this->FontSizePt,
				'font-stretch' => $this->font_stretching,
				'letter-spacing' => $this->font_spacing,
				'stroke' => $this->textstrokewidth,
				'fill' => (($this->textrendermode % 2) == 0),
				'clip' => ($this->textrendermode > 3),
				'line-height' => $this->cell_height_ratio,
				'bgcolor' => false,
				'fgcolor' => $this->fgcolor, // color
				'strokecolor' => $this->strokecolor,
				'align' => '',
				'listtype' => '',
				'text-indent' => 0,
				'text-transform' => '',
				'border' => array(),
				'dir' => $this->rtl?'rtl':'ltr',
				'width' => 0,
				'height' => 0,
				'x' => 0,
				'y' => 0,
				'w' => 0,
				'h' => 0,
				'l' => 0,
				't' => 0,
				'r' => 0,
				'b' => 0,
				'padding' => array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0),
				'margin' => array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0),
				'border-spacing' => array('H' => 0, 'V' => 0),
				'border-collapse' => 'separate',
			)
		);

		if(empty($html)) {
			return $dom;
		}
		$key = 1;
	 * Calculates the hash value of the given data.
	 *
	 * @param string $data The data to be hashed.
	 * @return string The hashed value of the data.
	protected function hashTCPDFtag($data) {
		return hash_hmac('sha256', $data, $this->hash_key, false);
	 * Serialize data to be used with TCPDF tag in HTML code.
	 * @param string $method TCPDF method name
	 * @param array $params Method parameters
	 * @return string Serialized data
	public function serializeTCPDFtag($method, $params=array()) {
		$data = array('m' => $method, 'p' => $params);
		$hash = $this->hashTCPDFtag($encoded);
		return strlen($hash).'+'.$hash.'+'.$encoded;
	 * Unserialize data to be used with TCPDF tag in HTML code.
	protected function unserializeTCPDFtag($data) {
		$hpos = strpos($data, '+');
		$hlen = intval(substr($data, 0, $hpos));
		$hash = substr($data, $hpos + 1, $hlen);
		$encoded = substr($data, $hpos + 2 + $hlen);
		if ($hash != $this->hashTCPDFtag($encoded)) {
	/**
	 * Check if a TCPDF tag is allowed
	 * @param string $method TCPDF method name
	 * @return boolean
	 * @protected
	 */
	protected function allowedTCPDFtag($method) {
		if (defined('K_ALLOWED_TCPDF_TAGS')) {
			return (strpos(K_ALLOWED_TCPDF_TAGS, '|'.$method.'|') !== false);
		}
		return false;
	}

	 * @param int $ln Indicates where the current position should go after the call. Possible values are:<ul><li>0: to the right (or left for RTL language)</li><li>1: to the beginning of the next line</li><li>2: below</li></ul> Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.
					// This tag is disabled by default by the K_TCPDF_CALLS_IN_HTML constant on TCPDF configuration file.
					// Please use this feature only if you are in control of the HTML content and you are sure that it does not contain any harmful code.
					if (!empty($tag['attribute']['data'])) {
						$tcpdf_tag_data = $this->unserializeTCPDFtag($tag['attribute']['data']);
						if ($this->allowedTCPDFtag($tcpdf_tag_data['m'])) {
							call_user_func_array(array($this, $tcpdf_tag_data['m']), $tcpdf_tag_data['p']);
						$this->newline = true;
		if (!isset($this->objcopy)) {
			return $this;
		}
		$file_id = $this->file_id;
		$objcopy = $this->objcopy;
		$this->_destroy(true, true);
		if ($self) {
			$objvars = get_object_vars($objcopy);
			foreach ($objvars as $key => $value) {
				$this->$key = $value;
			$objcopy->_destroy(true, true);
			unset($objcopy);
			return $this;
		$this->file_id = $file_id;
		return $objcopy;
		if ($stroke < 0 || !is_numeric($stroke)) {
if (!defined('K_ALLOWED_TCPDF_TAGS')) {
	define('K_ALLOWED_TCPDF_TAGS', '');
}

		$chr['8'] = '11101010111010';
		$seq = '1110111010';
		$seq .= '111010111';
    "license": "LGPL-3.0-or-later",
        "cs278/mktemp": "^1.2.0"