From: Nathan Kinsinger <[email protected]>

After the last line is read from the fileDescriptor the callee will call 
readLine once last time. If the (uninitialized) buffer just happened to contain 
'\r' then this method would increment bytesReceived, then decrement it (because 
it has '\r' in it), then decrement it agin and assign a null byte to the byte 
before the buffer (stepping on who knows what). Then it would return the '\r'. 
Then, since it received something, the callee would call readLine again, malloc 
would give the same buffer it did before (with the '\r') and everything would 
repeat.

    - initialize the buffer
    - increment bytesReceived only if a byte is actually received
    - don't do any work in the loop if there were no bytes received
    - EINTR is a recoverable error, just reread
    - give the actual reason for an error rather than some random string
    - free the buffer when a newline is found or when there is an error
---
 NSFileHandleExt.m |   42 ++++++++++++++++++++++++++----------------
 1 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/NSFileHandleExt.m b/NSFileHandleExt.m
index 2772855..731e4f1 100644
--- a/NSFileHandleExt.m
+++ b/NSFileHandleExt.m
@@ -27,36 +27,46 @@ -(NSString*)readLine {
        char *buffer = (char*)malloc(bufferSize + 1);
        if (buffer == NULL)
                [[NSException exceptionWithName:@"No memory left" reason:@"No 
more memory for allocating buffer" userInfo:nil] raise];
+       buffer[0] = '\0';
        
-       int bytesReceived = 0, n = 1;
+       int bytesReceived = 0, n = 0;
        
-       while (n > 0) {
-               n = read(fd, buffer + bytesReceived++, 1);
+       while (1) {
+               n = read(fd, buffer + bytesReceived, 1);
                
-               if (n < 0)
-                       [[NSException exceptionWithName:@"Socket error" 
reason:@"Remote host closed connection" userInfo:nil] raise];
+               if (n == 0)
+                       break;
+               
+               if (n < 0) {
+                       if (errno == EINTR)
+                               continue;
+
+                       free(buffer);
+                       NSString *reason = [NSString stringWithFormat:@"%s:%d: 
read() error: %s", __PRETTY_FUNCTION__, __LINE__, strerror(errno)];
+                       [[NSException exceptionWithName:@"Socket error" 
reason:reason userInfo:nil] raise];
+               }
+               
+               bytesReceived++;
                
                if (bytesReceived >= bufferSize) {
                        // Make buffer bigger
                        bufferSize += BUFFER_SIZE;
-                       buffer = (char*)realloc(buffer, bufferSize + 1);
+                       buffer = (char *)reallocf(buffer, bufferSize + 1);
                        if (buffer == NULL)
                                [[NSException exceptionWithName:@"No memory 
left" reason:@"No more memory for allocating buffer" userInfo:nil] raise];
                }       
                
-               switch (*(buffer + bytesReceived - 1)) {
-                       case '\n':
-                               buffer[bytesReceived-1] = '\0';
-                               NSString* s = [NSString stringWithCString: 
buffer encoding: NSUTF8StringEncoding];
-                               if ([s length] == 0)
-                                       s = [NSString stringWithCString: buffer 
encoding: NSISOLatin1StringEncoding];
-                               return s;
-                       case '\r':
-                               bytesReceived--;
+               char newByte = buffer[bytesReceived-1];
+               if (newByte == '\n') {
+                       bytesReceived--;
+                       break;
                }
+               
+               if (newByte == '\r')
+                       bytesReceived--;
        }       
        
-       buffer[bytesReceived-1] = '\0';
+       buffer[bytesReceived] = '\0';
        NSString *retVal = [NSString stringWithCString: buffer  encoding: 
NSUTF8StringEncoding];
        if ([retVal length] == 0)
                retVal = [NSString stringWithCString: buffer encoding: 
NSISOLatin1StringEncoding];
-- 
1.7.0

To unsubscribe from this group, send email to gitx+unsubscribegooglegroups.com 
or reply to this email with the words "REMOVE ME" as the subject.

Reply via email to