diff --git a/src/applications/diffusion/protocol/DiffusionSubversionWireProtocol.php b/src/applications/diffusion/protocol/DiffusionSubversionWireProtocol.php index 934969f792..e5645859a4 100644 --- a/src/applications/diffusion/protocol/DiffusionSubversionWireProtocol.php +++ b/src/applications/diffusion/protocol/DiffusionSubversionWireProtocol.php @@ -75,6 +75,10 @@ final class DiffusionSubversionWireProtocol extends Phobject { } } else if ($this->state == 'bytes') { $new_data = substr($this->buffer, 0, $this->expectBytes); + if (!strlen($new_data)) { + // No more bytes available yet, wait for more data. + break; + } $this->buffer = substr($this->buffer, strlen($new_data)); $this->expectBytes -= strlen($new_data); diff --git a/src/applications/diffusion/protocol/__tests__/DiffusionSubversionWireProtocolTestCase.php b/src/applications/diffusion/protocol/__tests__/DiffusionSubversionWireProtocolTestCase.php index 28b6473eb8..088f7222ed 100644 --- a/src/applications/diffusion/protocol/__tests__/DiffusionSubversionWireProtocolTestCase.php +++ b/src/applications/diffusion/protocol/__tests__/DiffusionSubversionWireProtocolTestCase.php @@ -61,6 +61,31 @@ final class DiffusionSubversionWireProtocolTestCase )); } + public function testSubversionWireProtocolPartialFrame() { + $proto = new DiffusionSubversionWireProtocol(); + + // This is primarily a test that we don't hang when we write() a frame + // which straddles a string boundary. + $msg1 = $proto->writeData('( duck 5:qu'); + $msg2 = $proto->writeData('ack ) '); + + $this->assertEqual(array(), ipull($msg1, 'structure')); + $this->assertEqual( + array( + array( + array( + 'type' => 'word', + 'value' => 'duck', + ), + array( + 'type'=> 'string', + 'value' => 'quack', + ), + ), + ), + ipull($msg2, 'structure')); + } + private function assertSameSubversionMessages($string, array $structs) { $proto = new DiffusionSubversionWireProtocol();