Converting F images to I turns large values, inf and NaN into -2147483648

Aperta Adatta ai principianti
#10,372 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@usmanmateen ci sta già lavorando.

Dal 31/10/2026.

  • #10373 di @usmanmateen — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c, python
Ambito
backend

Direzione di ricerca

Il bug è il cast non controllato i = f; nella funzione f2i in src/libImaging/Convert.c; clip32() in src/libImaging/Filter.c mostra la verifica dell'intervallo già presente da seguire. Riproduci con lo snippet Python della issue, poi conferma i risultati da F a I. È fatto quando i valori sopra l'intervallo di INT32 vengono limitati a 2147483647, -inf viene limitato a -2147483648, NaN diventa 0 e il round trip restituisce 2147483647.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Conversion
What did you do?

Converted a float (F) image with large or non-finite values to I, for example a float TIFF or a NumPy result with inf or NaN pixels, or an I image that went through F for processing:

import numpy as np
from PIL import Image

im = Image.fromarray(np.array([[1.5, 70000, 3e9, np.inf, -np.inf, np.nan]], np.float32), "F")
print("I", np.asarray(im.convert("I")).tolist())
print("L", np.asarray(im.convert("L")).tolist())

print(Image.new("I", (1, 1), 2**31 - 1).convert("F").convert("I").getpixel((0, 0)))
What did you expect to happen?

Values outside the I range clipped to it, the way F to L and F to I;16 clip to theirs, and the round trip to keep 2147483647:

I [[1, 70000, 2147483647, 2147483647, -2147483648, 0]]
L [[1, 255, 255, 255, 0, 0]]
2147483647
What actually happened?

Every value above the INT32 range, inf and NaN become -2147483648, the most negative value:

I [[1, 70000, -2147483648, -2147483648, -2147483648, -2147483648]]
L [[1, 255, 255, 255, 0, 0]]
-2147483648

The round trip fails because 2147483647 isn't representable as a float32 and rounds up to 2147483648.0, which is just past the INT32 range.

f2i in Convert.c casts with i = f; and no range check. Converting an out-of-range float or NaN to an integer is undefined behavior in C (-fsanitize=float-cast-overflow reports it), and the result depends on the CPU: x86 gives INT_MIN, while ARM saturates and gives INT32_MAX for large values and 0 for NaN. clip32() in Filter.c already guards the same overflow to INT_MIN.

I can open a PR that clips to the INT32 range in f2i and maps NaN to 0.

What are your OS, Python and Pillow versions?
  • OS: Ubuntu 26.04 (WSL2), x86-64
  • Python: 3.12.13
  • Pillow: 13.0.0
Lingua principale
Python
Stelle
14k
Fork
2.6k
Merge medio
1g 5h
PR unite (30g)
179

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di python-pillow/Pillow

Tutte le issue di python-pillow/Pillow

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.