From 99404f53c72965b41558aceb1bc2380875f5d848 Mon Sep 17 00:00:00 2001 From: Cyrus Leung Date: Fri, 2 May 2025 20:36:39 +0800 Subject: [PATCH] [Security] Fix image hash collision (#17378) Signed-off-by: DarkLight1337 --- tests/multimodal/assets/image1.png | Bin 0 -> 1837 bytes tests/multimodal/assets/image2.png | Bin 0 -> 1837 bytes tests/multimodal/test_hasher.py | 61 +++++++++++++++++++++++++++++ vllm/multimodal/hasher.py | 34 ++++++++++------ 4 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 tests/multimodal/assets/image1.png create mode 100644 tests/multimodal/assets/image2.png create mode 100644 tests/multimodal/test_hasher.py diff --git a/tests/multimodal/assets/image1.png b/tests/multimodal/assets/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..17c7d4cdffe914614b9f53622dbf91c9df9db310 GIT binary patch literal 1837 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJC2XHV0Nrr!y|1mHyGX(gAxc>kDA1DAJK~ke& zGz3Oc2&l||(+bQBFFaiwLn`LHnRRj2Vg(*I&rko}?}=A!VNtquZSJj^|L?3}WqqQ- z`A!6X(0mY2JRf~se(t7K@#P;5ZCLl{Xk_K)cFrxn)xYsZAS=YCERc=t5!#7y%QoD+?<6s{Gp(`~WWIwJdQ?|aUL?Gx&9 zcUOoNB`H)p#XT|SxcR-Hxh2||Dow<9?34p| z{;q9Hdpr-Xh}|pfyKU0(l9#1h-%2Fe8S4-zQ?cn zbxZh;wV_M7F4mXM%h@W?wqdVAsohp9(M?}7KHsU^{%z~rx8>5&8~b8;7Jdv{JoC%B zdY*Z`G8~)%pD&8>Y}#?N*a2ZgGC((O0?i z;E%yQHxDuAFsCIuQdO3P$8{W=X7j$NKewJaT`?p`v9@)wW5Q6dd zf30r$(z=&B^JaF3;+=BolX^3CT_^9W_h|7D2#OQGB;OUUtrBO$`nBwGyOT>)$hnp) zDvu&KHfZ+!Cq*t~k{qH2D1moTRt+=-p>tGaxCZceTD<(PQkJBK8f zcZdmh;cv@H`zBpExnb+7t2f&Z{;3Z=(~;t2AuMF4CnkR`%JZXBNrCO#yS~X@EB5Of zalUjc4_i1hSi=E8O;y1qZa}%-3KbbJ^WvzC&t^W11C-2HX{C_&My#Ar{ zujj2X7tc&xeeAwikzn|`M*>C03M`n}^oQ9$R!}|nk43I>)?XJOn}Na8)z4*}Q$iB} DJQVJy literal 0 HcmV?d00001 diff --git a/tests/multimodal/assets/image2.png b/tests/multimodal/assets/image2.png new file mode 100644 index 0000000000000000000000000000000000000000..0f13ce5d983d15565e1d3930b041f6917d95ce5f GIT binary patch literal 1837 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJC2XHV0Nrr!y|1mHyGX(gAxc>kDA0)!S0B1nB zqvU7^jD!$4!8XYNm=|7nx;TbZ%y~2G;;h9AJZ_$!{=MH5uiC<*bnDvOTQmRPS;NZu zM1%942>u}XAf9+W`nvqwO{?O|KOEYy?$Oc6%FV|gd*+5JDeVnu(byevK1+SRuu}5v zU$2i!cCOvZlr~Q*tohfD33Jc=oFeezT|Q;{x|W{z@p~Sh=Xm&pmCt>T zU-j#j@EvPImvUXKFP)dORibUfUWHP-tyZF&zGi&BQ@8!w*12!XrK30Y#quot7`Axk zmvi+z^Lk}CI0HUk6yw>n<7UehPOYyu&n&8$uiCvQnCBwv3cnq4InR>MM+MyC{K%uP za_7MxgL`fsV$NYsOLnBHEDMk8I5y4ZeNlgIJ#)HZNRVP}>te@_4;5_vk=H)T-Zxya zzV!$1ZokE1K28?>N>``2wk6qaHH=V}Qpzfw@h)M-nii4kA3Cl7Ropu5e^j7a@mG|d z;fm{5pS4Vw*RSeWD{^W1Z2r~)r6+%8eF#*1%BvXK>33S&sj6zqQGq<+~{<QZW8rT(;wjcacA9|)E#mPcg$WBj8{#=yjN2ihk+qZXplf72# z*EiyP>7Hb-`fuXlh`I06+U^%SnVH3JeCg*VVwHa~VcyGH?QmQD>t|2im4EpEbZB|~ zL+4-5TVpPsnY#MeeX%0J@O6&_ii{OlFth0ovwy6hO70(vT;;64E bytes: + return b''.join(kb + vb for kb, vb in cls.iter_item_to_bytes(key, obj)) + + @classmethod + def iter_item_to_bytes( + cls, + key: str, + obj: object, ) -> Iterable[tuple[bytes, bytes]]: # Recursive cases if isinstance(obj, (list, tuple)): for i, elem in enumerate(obj): - yield from cls.item_to_bytes(f"{key}.{i}", elem) + yield from cls.iter_item_to_bytes(f"{key}.{i}", elem) elif isinstance(obj, dict): for k, v in obj.items(): - yield from cls.item_to_bytes(f"{key}.{k}", v) + yield from cls.iter_item_to_bytes(f"{key}.{k}", v) else: key_bytes = cls.serialize_item(key) value_bytes = cls.serialize_item(obj) @@ -71,7 +83,7 @@ class MultiModalHasher: hasher = blake3() for k, v in kwargs.items(): - for k_bytes, v_bytes in cls.item_to_bytes(k, v): + for k_bytes, v_bytes in cls.iter_item_to_bytes(k, v): hasher.update(k_bytes) hasher.update(v_bytes)