While reading response from a socket, I get what I wrote earlier on it

This is about an implementation test of a soap client with just ANSI C standard libraries for an embedded system.

After sending my HTTP POST request to the server, I'm trying to save the SOAP XML document on response. But when I print the response I got, besides the whole XML document, it has appended the last 223 bytes written on the socket.

It doesn't seem that is a memory overlapping issue since docbuff_size = 1024 and response ends with 883 characters. I though that the UTF-8 encoding might be an issue but the I tried with different sizes of docbuff_size and buffer_size and I always got the same behavior.

If I write my buffer on stdout with fputs these tailing 223 bytes won't show. I build response with strncpy from what's in buffer. I think the problem is hidden on the different behaviors of these two functions.

This is a digested version of my code

...

int n;
char limiter[] = "\r\n\r\n";
bool first = true;
bool limiter_found = false;
char *pDocument = NULL;
char *pTmp = NULL;
unsigned int pDoc_len = 0;
char buffer[buffer_size] = {0};
char midbuff[10] = {0};
char response_code[4] = {0};
bzero(tmp, sizeof(tmp));

char *response;
response = malloc(docbuff_size);
bzero(response, sizeof(response));
bTotal = 0;
while ( (n = read(serverSocket, buffer, sizeof(buffer)-1) ) > 0)
{

    buffer[n] = '\0';

    ...

    // Case: limiter found in last iteration, then copy this buffer entirely
    if( pDocument != NULL && (bTotal+strlen(buffer)) < docbuff_size ){
        strncpy(response+bTotal, buffer, strlen(buffer));
        bTotal += strlen(buffer);
    }

    limiter_found = false;
    if( pTmp = strstr(buffer, limiter) ){
        pDocument = pTmp+4;
        limiter_found = true;
    } else if ( !first && (pTmp = strstr(midbuff, limiter)) ){
        // Take out 3 from the tail offset, add 4 from limiter length = 1
        pDocument = buffer + (pTmp - midbuff) + 1;
        limiter_found = true;
    }

    if(limiter_found){
        strncpy(response, pDocument, strlen(pDocument));
        bTotal += strlen(pDocument);
    }

    if(fputs(buffer, stdout) == EOF)
    {
        printf("\n Error : Fputs error\n");
    }
} 

if( response[0] != 0 ){
    printf("\n\nXML Document: \n"
        "*************************************\n"
        "%s\n"
        "*************************************\n", response);
}

if(n < 0)
{
    printf("\n Read error \n");
} 

if(response){
    free(response);
    response = NULL;
}

And this is an excerpt of the output

REQUEST SENT:
POST /xxxx/index.php HTTP/1.0
Host: testzzzzz.dev
User-agent: Blahblah
Content-type: text/xml; charset="iso-8859-1"
Content-length: 677
SOAPAction: "http://testzzzzz.dev/xxxx/index.php/ActionXXXX"

<?xml version="1.0" encoding="iso-8859-1"?><SOAP-ENV:Envelope  SOAP-  ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:xsd="http://www.w3.org/1999/XMLSchema"><SOAP-ENV:Body><ns1:ActionXXXX xmlns:ns1="http://testzzzzz.com/xxxx/nusoap" SOAP-ENC:root="1"><v1 xsi:type="xsd:string">Loremipsumdolorsitamet,consecteturadipisicingelit,seddoeiusmodtemporincididuntutlaboreetdoloremagnaaliqua.Utenimadminimveniam,quisnostrudexercitati</v1></ns1:ActionXXXX></SOAP-ENV:Body></SOAP-ENV:Envelope>

HTTP RESPONSE (written by fputs):
HTTP/1.1 200 OK
Date: Tue, 14 Jan 2014 18:11:39 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.4.9-4ubuntu2.4
X-SOAP-Server: DesiteG/0.9.5 (1.123)
Content-Length: 660
Vary: Accept-Encoding
Connection: close
Content-Type: text/xml; charset=UTF-8

<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:ActionXXXXResponse xmlns:ns1="http://testzzzzz.com/xxxx/nusoap"><return xsi:type="xsd:string">ResponseStringblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblaResponseString</return></ns1:ActionXXXXResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>

XML Document (build by strncpy): 
*************************************
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:ActionXXXXResponse xmlns:ns1="http://testzzzzz.com/xxxx/nusoap"><return xsi:type="xsd:string">ResponseStringblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblaResponseString</return></ns1:ActionXXXXResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>type="xsd:string">Loremipsumdolorsitamet,consecteturadipisicingelit,seddoeiusmodtemporincididuntutlaboreetdoloremagnaaliqua.Utenimadminimveniam,quisnostrudexercitati</v1></ns1:ActionXXXX></SOAP-ENV:Body></SOAP-ENV:Envelope>
*************************************

If you scroll to the left you can see where the difference between what fputs gets from what strncpy builds. The while last two iterations (the buffer gets used two times). It seems read on the last iteration puts some extra data on buffer that fputs correctly ignore but strncpy won't.

---- Edit (Solved, but I don't know why)----

Problem solved using strcpy instead of strncpy. It seems strlen(buffer) ignores the buffer[n] = '\0' written before.

strncpy(dest, src, strlen(src)); isn't the same as strcpy(dest, src);?

I want to leave this question open until a clear reason is explained.

Answers


As pointed by @Ron Burk bzero(response, sizeof(response)); is wrong.

Changed to the ANSI C compliant calloc

response = calloc( docbuff_size, sizeof(char) );

Solved the issue with strncpy though I'll use strcpy to improve readability.

What I think it happened is that response is being allocated on top of the variable where I wrote the request, then it wasn't being completely zero-ed and since strncpy doesn't add the final \0 like strcpy does then response would become a mix of old and new data.

It's not necessary to use calloc but it saves a line more.


Need Your Help

How to run this ActiveX based javascript in Firefox

javascript firefox firefox-addon activex activexobject

I am trying to run the below code which launches notepad. IE tab is nice solution, but loading is slow. I gave the try to ff-activex-host.I downloaded the binary exe. I copied the npffax.dll to fir...

.NET TransactionScope on Oracle

.net oracle transactionscope daab

we are using DAAB and TransactionScope on Oracle.