Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions src/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ natsMsgHeader_encodedLen(natsMsg *msg)
for (c = v; c != NULL; c = c->next)
{
hl += (int) strlen(key) + 2; // 2 for ": "
hl += (int) strlen(c->value) + _CRLF_LEN_;
hl += (int) (c->value == NULL ? 0 : strlen(c->value)) + _CRLF_LEN_;
}
}
natsStrHashIter_Done(&iter);
Expand Down Expand Up @@ -98,7 +98,7 @@ natsMsgHeader_encode(natsBuffer *buf, natsMsg *msg)
s = natsBuf_Append(buf, ": ", 2);
if (s == NATS_OK)
{
int vl = (int) strlen(c->value);
int vl = (c->value == NULL ? 0 : (int) strlen(c->value));
int pos = natsBuf_Len(buf);

s = natsBuf_Append(buf, (const char*) c->value, vl);
Expand Down Expand Up @@ -209,6 +209,8 @@ _processKeyValue(int line, natsMsg *msg, char *endPtr, char **pPtr, char **lastK
bool ml = false;
char *start;
char *endval;
bool isNullVal = false;
bool tmpCarRet = false;

start = ptr;
if (*ptr == '\r')
Expand Down Expand Up @@ -243,7 +245,19 @@ _processKeyValue(int line, natsMsg *msg, char *endPtr, char **pPtr, char **lastK
}

while ((ptr != endPtr) && (isspace((unsigned char) *ptr)))
{
if (tmpCarRet && (*ptr == '\n'))
{
// Value was NULL, or only whitespaces. Set pointer to before
// \r\n for further processing.
isNullVal = true;
ptr--;
break;
}

tmpCarRet = *ptr == '\r';
ptr++;
}

if (ptr == endPtr)
return nats_setError(NATS_PROTOCOL_ERROR, "no value found for key %s", key);
Expand All @@ -254,16 +268,26 @@ _processKeyValue(int line, natsMsg *msg, char *endPtr, char **pPtr, char **lastK
if (ptr == endPtr)
return nats_setError(NATS_PROTOCOL_ERROR, "no CRLF found for value of key %s", key);

// Trim right spaces and set to \0 to terminate the value string.
endval = ptr;
// Backtrack to \r and any space characters. Make sure we don't go
// past the beginning of the value pointer.
endval--;
if (*endval == '\r')
endval--;
while ((endval != val) && (isspace((unsigned char) *endval)))
if (isNullVal)
{
// For NULL or all-whitespace values, set the end value to the \r
// at the end.
endval = val;
}
else
{
// Trim right spaces and set to \0 to terminate the value string.
endval = ptr;
// Backtrack to \r and any space characters. Make sure we don't go
// past the beginning of the value pointer.
endval--;
endval++;
if (*endval == '\r')
endval--;
while ((endval != val) && (isspace((unsigned char)*endval)))
endval--;
endval++;
}

*(endval) = '\0';

if (ml)
Expand Down
69 changes: 57 additions & 12 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -5129,6 +5129,12 @@ void test_HeadersLift(void)
snprintf(buf, sizeof(buf), "%sk: a\r\n bc\r\n def\r\n\r\n", HDR_LINE);
_testHeader("Multiline values: ", buf, NATS_OK, "", "k", "a bc def");

snprintf(buf, sizeof(buf), "%sk:\r\n\r\n", HDR_LINE);
_testHeader("No value: ", buf, NATS_OK, "no value found for key", "k", "");

snprintf(buf, sizeof(buf), "%sk: \r\n\r\n", HDR_LINE);
_testHeader("No value (extra spaces): ", buf, NATS_OK, "no value found for key", "k", "");

snprintf(buf, sizeof(buf), "%s", "NATS\r\nk:v\r\n\r\n");
_testHeader("NATS header missing: ", buf, NATS_PROTOCOL_ERROR, "header prefix missing", NULL, NULL);

Expand All @@ -5144,12 +5150,6 @@ void test_HeadersLift(void)
snprintf(buf, sizeof(buf), "%sk\r\n\r\n", HDR_LINE);
_testHeader("Column missing: ", buf, NATS_PROTOCOL_ERROR, "column delimiter not found", NULL, NULL);

snprintf(buf, sizeof(buf), "%sk:\r\n\r\n", HDR_LINE);
_testHeader("No value: ", buf, NATS_PROTOCOL_ERROR, "no value found for key", NULL, NULL);

snprintf(buf, sizeof(buf), "%sk: \r\n\r\n", HDR_LINE);
_testHeader("No value (extra spaces): ", buf, NATS_PROTOCOL_ERROR, "no value found for key", NULL, NULL);

// Check status description in header line prefix...

snprintf(buf, sizeof(buf), "%s 503\r\n\r\n", HDR_LINE_PRE);
Expand Down Expand Up @@ -20072,12 +20072,14 @@ void test_HeadersNotSupported(void)
void test_HeadersBasic(void)
{
natsStatus s;
natsConnection *nc = NULL;
natsPid pid = NATS_INVALID_PID;
natsMsg *msg = NULL;
natsMsg *rmsg = NULL;
natsSubscription *sub = NULL;
const char *val = NULL;
natsConnection *nc = NULL;
natsPid pid = NATS_INVALID_PID;
natsMsg *msg = NULL;
natsMsg *rmsg = NULL;
natsSubscription *sub = NULL;
const char *val = NULL;
int count = 0;
const char **values = NULL;

if (!serverVersionAtLeast(2, 2, 0))
{
Expand Down Expand Up @@ -20109,6 +20111,24 @@ void test_HeadersBasic(void)
IFOK(s, natsMsgHeader_Set(msg, "Headers", "Hello Headers!"))
testCond(s == NATS_OK);

test("Add NULL header: ");
IFOK(s, natsMsgHeader_Add(msg, "NULL header", NULL))
testCond(s == NATS_OK);

test("Add empty header: ");
IFOK(s, natsMsgHeader_Add(msg, "Empty header", ""))
testCond(s == NATS_OK);

test("Add whitespace header: ");
IFOK(s, natsMsgHeader_Add(msg, "Whitespace header", " "))
testCond(s == NATS_OK);

test("Add NULL, empty, and whitespace values under same header: ");
IFOK(s, natsMsgHeader_Add(msg, "Special-Headers", NULL))
IFOK(s, natsMsgHeader_Add(msg, "Special-Headers", ""))
IFOK(s, natsMsgHeader_Add(msg, "Special-Headers", " "))
testCond(s == NATS_OK);

test("Publish with headers ok: ");
s = natsConnection_PublishMsg(nc, msg);
testCond(s == NATS_OK);
Expand All @@ -20134,6 +20154,31 @@ void test_HeadersBasic(void)
&& (natsMsg_GetDataLength(rmsg) == 4)
&& (strncmp(natsMsg_GetData(msg), "body", 4) == 0));

test("Check NULL header: ");
s = natsMsgHeader_Get(rmsg, "NULL header", &val);
testCond((s == NATS_OK)
&& (val != NULL) && *val == '\0');

test("Check empty header: ");
s = natsMsgHeader_Get(rmsg, "Empty header", &val);
testCond((s == NATS_OK)
&& (val != NULL) && *val == '\0');

test("Check whitespace header: ");
s = natsMsgHeader_Get(rmsg, "Whitespace header", &val);
testCond((s == NATS_OK)
&& (val != NULL) && *val == '\0');

test("Check getting values from special header: ");
s = natsMsgHeader_Values(rmsg, "Special-Headers", &values, &count);
testCond((s == NATS_OK) && (count == 3)
&& (values != NULL)
&& (*values[0] == '\0')
&& (*values[1] == '\0')
&& (*values[2] == '\0'));
free(values);
values = NULL;

natsMsg_Destroy(rmsg);
rmsg = NULL;
test("Value with CRLFs replaced with spaces: ");
Expand Down