php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #64670
Patch stomp-patch-content-length revision 2013-05-06 21:20 UTC by mi+php at aldan dot algebra dot com
revision 2013-05-06 15:35 UTC by mi+php at aldan dot algebra dot com
revision 2013-04-18 18:41 UTC by mi+php at aldan dot algebra dot com

Patch stomp-patch-content-length for stomp Bug #64670

Patch version 2013-04-18 18:41 UTC

Return to Bug #64670 | Download this patch
This patch is obsolete

Obsoleted by patches:

Patch Revisions: 2013-05-06 21:20 UTC | 2013-05-06 15:35 UTC | 2013-04-18 18:41 UTC

Developer: mi+php@aldan.algebra.com

Line 1 (now 1), was 20 lines, now 15 lines

  --- stomp.h	2012-11-18 17:35:40.000000000 -0500
 +++ stomp.h	2013-05-03 17:19:36.000000000 -0400
 @@ -82,7 +82,9 @@
  stomp_frame_t *stomp_read_frame(stomp_t *connection);
 +++ stomp.h	2013-04-17 16:41:22.000000000 -0400
 @@ -83,5 +83,5 @@
   int stomp_valid_receipt(stomp_t *connection, stomp_frame_t *frame);
 -int stomp_select(stomp_t *connection);
  int stomp_select(stomp_t *connection);
  -void stomp_set_error(stomp_t *stomp, const char *error, int errnum, const char *details);
 +int stomp_select_ex(stomp_t *connection, long sec, long usec);
  +void stomp_set_error(stomp_t *stomp, const char *error, int errnum, const char *fmt, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
   void stomp_free_frame(stomp_frame_t *frame);
 +
 +#define stomp_select(s) stomp_select_ex(s, s->options.read_timeout_sec, s->options.read_timeout_usec)
   #endif /* _STOMP_H_ */
  
  --- stomp.c	2012-11-18 17:35:40.000000000 -0500
 +++ stomp.c	2013-05-03 16:28:18.000000000 -0400
 +++ stomp.c	2013-04-18 12:22:03.000000000 -0400
  @@ -36,5 +36,6 @@
   /* {{{ stomp_init
    */
  -stomp_t *stomp_init() 
Line 37 (now 32), was 18 lines, now 17 lines

  +static stomp_frame_t *
  +stomp_frame_buffer_shift(stomp_frame_cell_t **pcell) {
   	stomp_frame_t *frame = NULL;
   	if (*pcell) {
 @@ -99,18 +102,24 @@
 @@ -99,5 +102,6 @@
   /* {{{ stomp_frame_buffer_clear
    */
  -void stomp_frame_buffer_clear(stomp_frame_cell_t **pcell) {
  +static void
  +stomp_frame_buffer_clear(stomp_frame_cell_t **pcell) {
   	stomp_frame_t *frame = NULL;
 -	while (frame = stomp_frame_buffer_shift(pcell)) efree(frame);
 +	while ((frame = stomp_frame_buffer_shift(pcell))) efree(frame);
  }
  	while (frame = stomp_frame_buffer_shift(pcell)) efree(frame);
 @@ -105,12 +109,17 @@
   /* }}} */
   
  -/* {{{ stomp_set_error 
  +/* {{{ stomp_set_error
Line 168 (now 162), was 23 lines, now 20 lines

  @@ -221,5 +247,6 @@
   /* {{{ stomp_close
    */
  -void stomp_close(stomp_t *stomp)
 +void
 +void
  +stomp_close(stomp_t *stomp)
   {
   	if (NULL == stomp) {
 @@ -254,7 +281,8 @@
 @@ -254,5 +281,6 @@
   /* {{{ stomp_send
    */
  -int stomp_send(stomp_t *stomp, stomp_frame_t *frame TSRMLS_DC)
  +int
  +stomp_send(stomp_t *stomp, stomp_frame_t *frame TSRMLS_DC)
   {
 -	smart_str buf = {0};
 +	smart_str buf = { .c = NULL };
  
  	/* Command */
  	smart_str buf = {0};
  @@ -265,15 +293,15 @@
   	if (frame->headers) {
   
  -		char *key; 
Line 194 (now 185), was 23 lines, now 17 lines

   
   		while (zend_hash_get_current_key(frame->headers, &key, &pos, 0) == HASH_KEY_IS_STRING) {
  -			char *value = NULL;
  +			void *value = NULL;
  
  
   			smart_str_appends(&buf, key);
   			smart_str_appendc(&buf, ':');
   
  -			if (zend_hash_get_current_data(frame->headers, (void **)&value) == SUCCESS) {
  +			if (zend_hash_get_current_data(frame->headers, &value) == SUCCESS) {
   				smart_str_appends(&buf, value);
   			}
 @@ -293,13 +321,11 @@
  	smart_str_appendc(&buf, '\n');
  
 -	if (frame->body > 0) {
 +	if (frame->body) {
  		smart_str_appendl(&buf, frame->body, frame->body_length > 0 ? frame->body_length : strlen(frame->body));
  	}
 @@ -298,8 +326,6 @@
   
   	if (!stomp_writeable(stomp)) {
  -		char error[1024];
  -		snprintf(error, sizeof(error), "Unable to send data");


  +#else
  +		    "not "
  +#endif
  +		);
  		stomp->status = -1;
 +		stomp->status = -1;
  +		break;
  +	case 0:
  +		stomp_set_error(stomp, "Sender closed connection unexpectedly",
  +		    0, NULL);
 +		stomp->status = -1;
  		stomp->status = -1;
  +		break;
   	}
   	return len;
 @@ -358,55 +400,68 @@
 @@ -358,55 +400,77 @@
   /* }}} */
  
  
  -/* {{{ stomp_read_buffer 
  +/* {{{ stomp_recv_full
 + */
   */
 -static int stomp_read_buffer(stomp_t *stomp, char **data)
  +static int
  +stomp_recv_full(stomp_t *stomp, char *msg, size_t length)
 +{
  {
 -	int rc = 0;
  +	int	i;
  +	size_t	length_read = 0;
  +
  +	while (length_read < length) {
Line 315 (now 302), was 30 lines, now 28 lines

  +	return length_read;
  +}
  +/* }}} */
  +
 +
 +
  +/* {{{ stomp_read_buffer
   */
 -static int stomp_read_buffer(stomp_t *stomp, char **data)
 + */
  +static int
  +stomp_read_buffer(stomp_t *stomp, char **data)
  {
 -	int rc = 0;
 +	int rc;
  	size_t i = 0;
  	size_t bufsize = STOMP_BUFSIZE + 1;
 -	char *buffer = (char *) emalloc(STOMP_BUFSIZE + 1);
 +	char *buffer = emalloc(STOMP_BUFSIZE + 1);
  
  	while (1) {
 -
 -		size_t length = 1;
 -		rc = stomp_recv(stomp, buffer + i, length);
 +		rc = stomp_recv(stomp, buffer + i, 1);
  		if (rc < 1) {
 +{
 +	int rc;
  	size_t i = 0;
  	size_t bufsize = STOMP_BUFSIZE + 1;
 -	char *buffer = (char *) emalloc(STOMP_BUFSIZE + 1);
 +	char *buffer = emalloc(STOMP_BUFSIZE + 1);
  
  	while (1) {
 -
 -		size_t length = 1;
 -		rc = stomp_recv(stomp, buffer + i, length);
 +		rc = stomp_recv(stomp, buffer + i, 1);
  		if (rc < 1) {
  -			efree(buffer);
 +			efree(buffer); /* stomp_recv already set error */
 +			efree(buffer); /* stomp_recv already threw */
   			return -1;
   		}
   
  -		if (1 == length) {


  -					efree(buffer);
  -					return 0;
  -				}
  -				break;
 -			}
 +		if (buffer[i] == '\0')
 +		if (buffer[i] == '\0') {
 +			char endline[1];
 +			if (1 != stomp_recv(stomp, endline, 1) && '\n' != endline[0]) {
 +				efree(buffer);
 +				stomp_set_error(stomp, "Protocol violation", 0,
 +				    "The byte after nil is %hu, rather than newline",
 +				    (unsigned short)endline[0]);
 +				return 0;
  			}
  +			break;
 +		}
   
  -			if (i >= bufsize) {
  -				buffer = (char *) erealloc(buffer, bufsize + STOMP_BUFSIZE);
  -				bufsize += STOMP_BUFSIZE;


  -	return i-1;
  +	return i;
   }
   /* }}} */
 @@ -414,15 +469,14 @@
 @@ -414,15 +478,14 @@
   /* {{{ stomp_read_line
    */
  -static int stomp_read_line(stomp_t *stomp, char **data)
  +static int
 +stomp_read_line(stomp_t *stomp, char **data, int drain)
 +stomp_read_line(stomp_t *stomp, char **data)
   {
  -	int rc = 0;
  +	int rc;
   	size_t i = 0;
Line 407 (now 400), was 31 lines, now 22 lines

  -		rc = stomp_recv(stomp, buffer + i, length);
  +		rc = stomp_recv(stomp, buffer + i, 1);
   		if (rc < 1) {
   			efree(buffer);
 @@ -430,36 +484,41 @@
 @@ -430,36 +493,32 @@
   		}
   
  -		if (1 == length) {
  -			i++; 
  +		if (buffer[i] == '\n') {
 +			/*
 +			 * Drain leading newlines, if any, that the STOMP
 +			 * protocol allows after the nul-byte of an earlier
 +			 * frame:
 +			 *  http://stomp.github.io/stomp-specification-1.1.html
 +			 */
 +			if (drain)
 +				continue;
  +			buffer[i] = '\0';
  +			break;
  +		} else if (buffer[i] == '\0') {
  +			efree(buffer);
  +			stomp_set_error(stomp, "Protocol violation", 0,
  +			    "Sender sent 0-byte before the newline");
  +			return 0;
  +		}
 +		drain = 0;
   
  -			if (buffer[i-1] == '\n') {
  -				buffer[i-1] = 0;
  -				break;
Line 494 (now 478), was 41 lines, now 27 lines

  -	char *cmd = NULL, *length_str = NULL;
  -	int length = 0;
  +	char *cmd = NULL;
  +	int length;
 +	char endbyte;
 +	char endbuffer[2];
   
   	if (stomp->buffer) {
 @@ -498,4 +560,9 @@
  
  	if (!stomp_select(stomp)) {
 +		stomp_set_error(stomp, "Timeout", 0, "No data available "
 +		    "within the specified timeout ",
 +		    "(%ld seconds, %ld microseconds)",
 +		    stomp->options.read_timeout_sec,
 +		    stomp->options.read_timeout_sec);
  		return NULL;
  	}
 @@ -507,6 +574,8 @@
 @@ -507,4 +569,6 @@
   	}
   
  +	f->body_length = -1;
 +
 +
   	/* Parse the command */
 -	length = stomp_read_line(stomp, &cmd);
 +	length = stomp_read_line(stomp, &cmd, 1);
  	if (length < 1) {
  		RETURN_READ_FRAME_FAIL;
 @@ -518,54 +587,91 @@
  	length = stomp_read_line(stomp, &cmd);
 @@ -518,54 +582,76 @@
   	/* Parse the header */
   	while (1) {
  -		char *p = NULL;
 -		length = stomp_read_line(stomp, &p);
 -		
  +		char	*p, *p2, *key, *value;
  +		size_t	 keylen, vallen;
  +
 +		length = stomp_read_line(stomp, &p, 0);
  		length = stomp_read_line(stomp, &p);
 -		
  +
   		if (length < 0) {
   			RETURN_READ_FRAME_FAIL;
   		}
Line 546 (now 516), was 24 lines, now 21 lines

  -			if (p2 == NULL) {
  -				efree(p);
  -				RETURN_READ_FRAME_FAIL;
  -			}
 -
  
  -			/* Null terminate the key */
  -			*p2=0;
  -			key = p;
 +		p2 = strchr(p, ':');
   
  -			/* The rest is the value. */
  -			value = p2+1;
 +		p2 = strchr(p, ':');
  
 -
  -			/* Insert key/value into hash table. */
  -			zend_hash_add(f->headers, key, strlen(key) + 1, value, strlen(value) + 1, NULL);
  +		if (p2 == NULL) {
   			efree(p);
 +			stomp_set_error(stomp, "Protocol violation", 0,
 +			    "Header section contains a string without ",
 +			    "colon: %.*s", length, p);
  +			RETURN_READ_FRAME_FAIL;
   		}
  -	}
   
Line 581 (now 548), was 9 lines, now 8 lines

  +		vallen = length - keylen - 1;
  +
  +		/* Check, if the header specifies content-length */
  +		if (keylen == sizeof("content-length") - 1 &&
 +		    key[0] == 'c' &&
  +		    strcmp("content-length", key) == 0) {
  +			char	*ep;
  +			long	 lbodylen = strtol(value, &ep, 0);
  +
Line 621 (now 587), was 31 lines, now 20 lines

  -
  -		if (length != stomp_recv(stomp, endbuffer, length) || endbuffer[0] != '\0' || endbuffer[1] != '\n') {
  +		/* FALLTHROUGH */
  +	case 0:	/* Content-length is explicitly specified as zero */
 +		switch (stomp_recv_full(stomp, &endbyte, 1)) {
 +		case 0:
 +			stomp_set_error(stomp, "Protocol violation", 0,
 +			    "Could not read the ending of the frame");
 +			/* FALLTHROUGH */
 +		case -1:
 +			/* stomp_recv already complained about error */
 +			RETURN_READ_FRAME_FAIL;
 +		case 1:
 +			if (endbyte == '\0')
 +				break; /* Excellent */
 +		if (stomp_recv(stomp, endbuffer, 2) != 2 ||
 +		    endbuffer[0] != '\0' || endbuffer[1] != '\n') {
  +			stomp_set_error(stomp, "Protocol violation", 0,
 +			    "Ending byte frame read -- "
 +			    "0x%hhx -- is not \\0",
 +			    endbyte);
 +			    "Could not read the two closing bytes of the frame");
   			RETURN_READ_FRAME_FAIL;
   		}
  -	} else {
  +		break;
  +	case -1: /* Content-length not found among the headers */
   		f->body_length = stomp_read_buffer(stomp, &f->body);
   	}
 @@ -577,10 +683,10 @@
 @@ -577,10 +663,10 @@
   /* {{{ stomp_valid_receipt
    */
  -int stomp_valid_receipt(stomp_t *stomp, stomp_frame_t *frame) {
  +int


  -	if (zend_hash_find(frame->headers, "receipt", sizeof("receipt"), (void **)&receipt) == SUCCESS) {
  +	if (zend_hash_find(frame->headers, "receipt", sizeof("receipt"), &receipt) == SUCCESS) {
   		stomp_frame_cell_t *buffer = NULL;
   		success = 0;
 @@ -589,12 +695,11 @@
 @@ -589,12 +675,11 @@
   			if (res) {
   				if (0 == strncmp("RECEIPT", res->command, sizeof("RECEIPT") - 1)) {
  -					char *receipt_id = NULL;
  -					if (zend_hash_find(res->headers, "receipt-id", sizeof("receipt-id"), (void **)&receipt_id) == SUCCESS


  -						stomp_set_error(stomp, error, 0, NULL);
  +						stomp_set_error(stomp, "Unexpected receipt id", 0, "%s", receipt_id);
   					}
   					stomp_free_frame(res);
 @@ -602,8 +707,8 @@
 @@ -602,8 +687,8 @@
   					return success;
   				} else if (0 == strncmp("ERROR", res->command, sizeof("ERROR") - 1)) {
  -					char *error_msg = NULL;
  -					if (zend_hash_find(res->headers, "message", sizeof("message"), (void **)&error_msg) == SUCCESS) {
Line 687 (now 642), was 25 lines, now 17 lines

  +					stomp_set_error(stomp, error_msg ? error_msg : "ERROR", 0,
  +					    res->body ? "%s" : NULL, res->body);
   					stomp_free_frame(res);
   					stomp->buffer = buffer;
 @@ -624,5 +729,6 @@
 @@ -624,5 +709,6 @@
   /* {{{ stomp_select
    */
  -int stomp_select(stomp_t *stomp)
  +int
 +stomp_select_ex(stomp_t *stomp, long sec, long usec)
 +stomp_select(stomp_t *stomp)
   {
   	int     n;
 @@ -633,14 +739,14 @@
  	}
  
 -	tv.tv_sec = stomp->options.read_timeout_sec;
 -	tv.tv_usec = stomp->options.read_timeout_usec;
 +	tv.tv_sec = sec;
 +	tv.tv_usec = usec;
  
  	n = php_pollfd_for(stomp->fd, PHP_POLLREADABLE, &tv);
 @@ -639,8 +725,8 @@
   	if (n < 1) {
   #if !defined(PHP_WIN32) && !(defined(NETWARE) && defined(USE_WINSOCK))
  -		if (n == 0) { 
  +		if (n == 0) {
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat May 18 15:01:33 2024 UTC