Intervention/image · warning · AnalyzerException

Unable to read exif data, division by zero

Error message

Unable to read exif data, division by zero

What it means

EXIF stores resolutions as rationals like "72/1". The parser splits on '/', intval()s both parts, and if the denominator is 0 it refuses to divide and throws instead of producing INF/NAN. This indicates a corrupt or hostile EXIF block. The exception is caught by the recovery chain and never surfaces through the public resolution() API.

Source

Thrown at src/Drivers/Gd/Analyzers/ResolutionAnalyzer.php:169

        }

        if (isset($data['IFD0']) && isset($data['IFD0']['XResolution']) && isset($data['IFD0']['YResolution'])) {
            $resolution = [$data['IFD0']['XResolution'], $data['IFD0']['YResolution']];
        }

        if (!isset($resolution)) {
            throw new AnalyzerException('Unable to read exif data');
        }

        return array_map(function (mixed $value): int|float {
            if (strpos($value, '/') === false) {
                return $value;
            }

            $values = array_map(fn(string $value): int => intval($value), explode('/', $value));

            if ($values[1] === 0) {
                throw new AnalyzerException('Unable to read exif data, division by zero');
            }

            return $values[0] / $values[1];
        }, $resolution);
    }

    /**
     * @param resource $handle
     * @throws AnalyzerException
     * @return array<float>
     */
    private function resolutionFromPngPhys($handle): array
    {
        rewind($handle);
        $signature = fread($handle, 8);

        // no PNG content
        if ($signature !== "\x89PNG\x0D\x0A\x1A\x0A") {

View on GitHub (pinned to 5598b9e397)

Solutions

  1. Nothing to fix at call time — the analyzer falls back to 96 DPI
  2. Sanitize at ingest: reject or re-encode uploads whose exif_read_data() rationals contain zero denominators
  3. Repair the file with exiftool -xresolution=72/1 -yresolution=72/1 if it must be kept

Example fix

// ingest-time guard
$exif = @exif_read_data($path) ?: [];
foreach (['XResolution', 'YResolution'] as $tag) {
    $v = $exif['IFD0'][$tag] ?? $exif[$tag] ?? null;
    if (is_string($v) && preg_match('#/(\d+)$#', $v, $m) && (int) $m[1] === 0) {
        // reject or re-encode: zero denominator in EXIF rational
    }
}
Defensive patterns

Strategy: fallback

Validate before calling

foreach (['XResolution', 'YResolution'] as $tag) {
    $v = $exif['IFD0'][$tag] ?? $exif[$tag] ?? null;
    if (is_string($v) && str_contains($v, '/') && (int) substr($v, strpos($v, '/') + 1) === 0) {
        // zero denominator: file will fail EXIF recovery
    }
}

Prevention

When it happens

Trigger: A crafted or damaged JPEG/TIFF whose XResolution is e.g. "300/0"; files edited by tools that write zero denominators into rational tags.

Common situations: Fuzzed or truncated uploads; images processed by buggy metadata writers; penetration-test fixtures.

Related errors


AI-assisted analysis of Intervention/image@5598b9e397 (2026-08-23). Data as JSON: /api/errors/ebc1746d0a1dc2cc. Report an issue: GitHub.