Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions litellm/litellm_core_utils/prompt_templates/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import litellm.types.llms
from litellm import verbose_logger
from litellm._uuid import uuid
from litellm.litellm_core_utils.url_utils import async_safe_get, safe_get
from litellm.llms.custom_httpx.http_handler import HTTPHandler, get_async_httpx_client
from litellm.types.files import get_file_extension_from_mime_type
from litellm.types.llms.anthropic import *
Expand Down Expand Up @@ -3324,7 +3325,7 @@ def _load_image_from_url(image_url):
try:
# Send a GET request to the image URL
client = HTTPHandler(concurrent_limit=1)
response = client.get(image_url)
response = safe_get(client, image_url)
response.raise_for_status() # Raise an exception for HTTP errors

# Check the response's content type to ensure it is an image
Expand Down Expand Up @@ -3562,7 +3563,7 @@ async def get_image_details_async(image_url) -> Tuple[str, str]:
params={"concurrent_limit": 1},
)
# Send a GET request to the image URL
response = await client.get(image_url, follow_redirects=True)
response = await async_safe_get(client, image_url)
response.raise_for_status() # Raise an exception for HTTP errors

return BedrockImageProcessor._post_call_image_processing(
Expand All @@ -3577,7 +3578,7 @@ def get_image_details(image_url) -> Tuple[str, str]:
try:
client = HTTPHandler(concurrent_limit=1)
# Send a GET request to the image URL
response = client.get(image_url, follow_redirects=True)
response = safe_get(client, image_url)
response.raise_for_status() # Raise an exception for HTTP errors

return BedrockImageProcessor._post_call_image_processing(
Expand Down
7 changes: 7 additions & 0 deletions litellm/litellm_core_utils/token_counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
DEFAULT_IMAGE_HEIGHT,
DEFAULT_IMAGE_TOKEN_COUNT,
DEFAULT_IMAGE_WIDTH,
MAX_IMAGE_URL_DOWNLOAD_SIZE_MB,
MAX_LONG_SIDE_FOR_IMAGE_HIGH_RES,
MAX_SHORT_SIDE_FOR_IMAGE_HIGH_RES,
MAX_TILE_HEIGHT,
Expand Down Expand Up @@ -215,7 +216,13 @@ def get_image_dimensions(
try:
client = _get_httpx_client()
response = safe_get(client, data)
max_bytes = int(MAX_IMAGE_URL_DOWNLOAD_SIZE_MB * 1024 * 1024)
content_length = response.headers.get("Content-Length")
if content_length is not None and int(content_length) > max_bytes:
raise ValueError("Image response exceeds size limit")
img_data = response.read()
if len(img_data) > max_bytes:
raise ValueError("Image response exceeds size limit")
Comment on lines 223 to +225

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Post-read size check still buffers entire response into memory

response.read() fully buffers the response body before the len(img_data) > max_bytes check fires. If the server omits Content-Length (or sends a deliberately low value), a very large image can exhaust heap before the guard triggers. The existing image_handling.py avoids this with iter_bytes(chunk_size=8192) and an in-flight byte counter. Aligning with that approach here would give a hard memory cap rather than just a post-hoc check.

except Exception:
pass
if img_data is None:
Expand Down
Loading