Projects
home:rottame:vhosts-ng:php74
php7
php7-CVE-2026-6103.patch
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File php7-CVE-2026-6103.patch of Package php7
From 0994e2e887cd993866b5e4d7dba2fade5caeefec Mon Sep 17 00:00:00 2001 From: Jakub Zelenka <bukka@php.net> Date: Sun, 13 Sep 2026 22:37:00 +0200 Subject: [PATCH] Fix GHSA-j3wh-g957-2m85: phar tar entry injection Reject entry sizes that cannot be parsed or represented, and skip the data blocks of every entry type that carries data. Both left the stream on attacker controlled data that was then parsed as a tar header. --- ext/phar/phar_internal.h | 5 + ext/phar/tar.c | 80 +++++++++++++++- .../tar/GHSA-j3wh-g957-2m85-longlink.phpt | 50 ++++++++++ .../tests/tar/GHSA-j3wh-g957-2m85-size.phpt | 92 +++++++++++++++++++ .../tar/GHSA-j3wh-g957-2m85-typeflag.phpt | 79 ++++++++++++++++ 5 files changed, 301 insertions(+), 5 deletions(-) create mode 100644 ext/phar/tests/tar/GHSA-j3wh-g957-2m85-longlink.phpt create mode 100644 ext/phar/tests/tar/GHSA-j3wh-g957-2m85-size.phpt create mode 100644 ext/phar/tests/tar/GHSA-j3wh-g957-2m85-typeflag.phpt Index: php-7.4.33/ext/phar/phar_internal.h =================================================================== --- php-7.4.33.orig/ext/phar/phar_internal.h +++ php-7.4.33/ext/phar/phar_internal.h @@ -113,8 +113,13 @@ #define TAR_FILE '0' #define TAR_LINK '1' #define TAR_SYMLINK '2' +#define TAR_CHAR '3' +#define TAR_BLOCK '4' #define TAR_DIR '5' +#define TAR_FIFO '6' #define TAR_NEW '8' +#define TAR_LONGLINK 'K' +#define TAR_LONGNAME 'L' #define TAR_GLOBAL_HDR 'g' #define TAR_FILE_HDR 'x' Index: php-7.4.33/ext/phar/tar.c =================================================================== --- php-7.4.33.orig/ext/phar/tar.c +++ php-7.4.33/ext/phar/tar.c @@ -37,6 +37,52 @@ static uint32_t phar_tar_number(char *bu } /* }}} */ +static zend_bool phar_tar_type_has_data(char typeflag) +{ + switch (typeflag) { + case TAR_LINK: + case TAR_SYMLINK: + case TAR_CHAR: + case TAR_BLOCK: + case TAR_DIR: + case TAR_FIFO: + return 0; + default: + return 1; + } +} + +static zend_bool phar_tar_size(const char *buf, size_t len, uint32_t *result) +{ + uint64_t num = 0; + size_t i = 0; + + while (i < len && buf[i] == ' ') { + ++i; + } + + /* GNU base-256 encoding is only used for sizes that do not fit the octal field */ + if (i < len && (((unsigned char) buf[i]) & 0x80)) { + return 0; + } + + while (i < len && buf[i] >= '0' && buf[i] <= '7') { + num = num * 8 + (buf[i] - '0'); + ++i; + } + + while (i < len && (buf[i] == ' ' || buf[i] == '\0')) { + ++i; + } + + if (i != len || num > UINT32_MAX - 511) { + return 0; + } + + *result = (uint32_t) num; + return 1; +} + /* adapted from format_octal() in libarchive * * Copyright (c) 2003-2009 Tim Kientzle @@ -280,8 +326,32 @@ int phar_parse_tarfile(php_stream* fp, c } } - size = entry.uncompressed_filesize = entry.compressed_filesize = - phar_tar_number(hdr->size, sizeof(hdr->size)); + if (!phar_tar_size(hdr->size, sizeof(hdr->size), &size)) { + if (error) { + spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (invalid entry size)", fname); + } + if (last_was_longlink) { + pefree(entry.filename, myphar->is_persistent); + } + php_stream_close(fp); + phar_destroy_phar_data(myphar); + return FAILURE; + } + entry.uncompressed_filesize = entry.compressed_filesize = size; + + /* GNU long link names are not supported, so refuse the record instead of + * registering it as an entry and dropping the link target of the entry that follows */ + if (hdr->typeflag == TAR_LONGLINK) { + if (error) { + spprintf(error, 4096, "phar error: \"%s\" is a tar file with an unsupported GNU long link entry", fname); + } + if (last_was_longlink) { + pefree(entry.filename, myphar->is_persistent); + } + php_stream_close(fp); + phar_destroy_phar_data(myphar); + return FAILURE; + } /* skip global/file headers (pax) */ if (!old && (hdr->typeflag == TAR_GLOBAL_HDR || hdr->typeflag == TAR_FILE_HDR)) { @@ -369,13 +439,13 @@ bail: goto bail; } - if (!last_was_longlink && hdr->typeflag == 'L') { + if (!last_was_longlink && hdr->typeflag == TAR_LONGNAME) { last_was_longlink = 1; /* support the ././@LongLink system for storing long filenames */ entry.filename_len = entry.uncompressed_filesize; /* Check for overflow - bug 61065 */ - if (entry.filename_len == UINT_MAX || entry.filename_len == 0) { + if (entry.filename_len == 0 || entry.filename_len > totalsize) { if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (invalid entry size)", fname); } @@ -585,7 +655,7 @@ bail: size = (size+511)&~511; - if (((hdr->typeflag == '\0') || (hdr->typeflag == TAR_FILE)) && size > 0) { + if (phar_tar_type_has_data(hdr->typeflag) && size > 0) { next: /* this is not good enough - seek succeeds even on truncated tars */ php_stream_seek(fp, size, SEEK_CUR);
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.