guzzle/guzzle3 — pull request #46 by nikosdion (2014-11-22 22:32:03+00:00)
Title: Memory exhausted processing large streams

# Executive summary

Memory exhaustion error when using ReadLimitEntityBody with streams larger thant the available PHP memory.

# Technical explanation

The __toString() method in Guzzle\Http\ReadLimitEntityBody will try to read the entire stream into memory, then use substr() to select a subset. If you have a stream larger than the available PHP memory your script will crash due to lack of sufficient PHP memory.

This can be fixed by duplicating some of the code in Guzzle\Stream\Stream's __toString method. This allows us to only read into memory the part of the stream defined by the $limit and $offset in the ReadLimitEntityBody instance. It's not as elegant or academically correct as the existing code but it solves a serious practical shortcoming.

# Use case

I've hit this issue while using Amazon SDK for PHP to perform a multipart upload of a 2Gb file to S3 using the AWS4 (v4) signature method. When using the unmodified Guzzle 3 sources it resulted in an immediate PHP memory limit error. After the proposed change the upload completes successfully.

# Backwards compatibility issues

No backwards compatibility issues are expected. The proposed change is enclosed in an if-block which makes it run only when $body implements StreamInterface. In any other case it works as a simple decorator (prior behaviour).