Skip to content

Commit

Permalink
Revise examples to limit buffer size.
Browse files Browse the repository at this point in the history
Adrian says it's dumb to let hostile input grow your buffers
arbitrarily long, and he's right.  Also, drop some debugging code from
the libevent example.
  • Loading branch information
nmathewson committed Feb 8, 2009
1 parent 6c551c0 commit 758f12f
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 113 deletions.
19 changes: 18 additions & 1 deletion examples_01/01_rot13_server_bufferevent.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <stdio.h>
#include <errno.h>

#define MAX_LINE 16384

void do_read(evutil_socket_t fd, short events, void *arg);
void do_write(evutil_socket_t fd, short events, void *arg);

Expand All @@ -38,15 +40,29 @@ readcb(struct bufferevent *bev, void *ctx)
struct evbuffer *input, *output;
char *line;
size_t n;
int i;
input = bufferevent_get_input(bev);
output = bufferevent_get_output(bev);

while ((line = evbuffer_readln(input, &n, EVBUFFER_EOL_LF))) {
int i;
for (i = 0; i < n; ++i)
line[i] = rot13_char(line[i]);
evbuffer_add(output, line, n);
evbuffer_add(output, "\n", 1);
free(line);
}

if (evbuffer_get_length(input) >= MAX_LINE) {
/* Too long; just process what there is and go on so that the buffer
* doesn't grow infinitely long. */
char buf[1024];
while (evbuffer_get_length(input)) {
int n = evbuffer_remove(input, buf, sizeof(buf));
for (i = 0; i < n; ++i)
line[i] = rot13_char(line[i]);
evbuffer_add(output, buf, n);
}
evbuffer_add(output, "\n", 1);
}
}

Expand All @@ -72,6 +88,7 @@ do_accept(evutil_socket_t listener, short event, void *arg)
evutil_make_socket_nonblocking(fd);
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, readcb, NULL, errorcb, NULL);
bufferevent_setwatermark(bev, EV_READ, 0, MAX_LINE);
bufferevent_enable(bev, EV_READ|EV_WRITE);
}
}
Expand Down
24 changes: 6 additions & 18 deletions examples_01/01_rot13_server_forking.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <stdio.h>
#include <stdlib.h>

#define MAX_LINE 16384

char
rot13_char(char c)
{
Expand All @@ -24,17 +26,10 @@ rot13_char(char c)
void
child(int fd)
{
char *outbuf;
size_t outbuf_len = 1024;
char outbuf[MAX_LINE+1];
size_t outbuf_used = 0;
ssize_t result;

outbuf = malloc(outbuf_len);
if (!outbuf) {
perror("malloc");
exit(1);
}

while (1) {
char ch;
result = recv(fd, &ch, 1, 0);
Expand All @@ -45,18 +40,11 @@ child(int fd)
break;
}

if (outbuf_used == outbuf_len) {
char *outbuf2 = realloc(outbuf, outbuf_len*2);
if (outbuf2 == NULL) {
perror("realloc");
break;
}
outbuf = outbuf2;
outbuf_len *= 2;
/* We do this test to keep the user from overflowing the buffer. */
if (outbuf_used < sizeof(outbuf)) {
outbuf[outbuf_used++] = rot13_char(ch);
}

outbuf[outbuf_used++] = rot13_char(ch);

if (ch == '\n') {
send(fd, outbuf, outbuf_used, 0);
outbuf_used = 0;
Expand Down
74 changes: 5 additions & 69 deletions examples_01/01_rot13_server_libevent.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <stdio.h>
#include <errno.h>

#define MAX_LINE 16384

void do_read(evutil_socket_t fd, short events, void *arg);
void do_write(evutil_socket_t fd, short events, void *arg);

Expand All @@ -31,15 +33,13 @@ rot13_char(char c)
}

struct fd_state {
char *buffer;
size_t buffer_len;
char buffer[MAX_LINE];
size_t buffer_used;

size_t n_written;
size_t write_upto;

struct event *read_event;
char junk[16];
struct event *write_event;
};

Expand All @@ -49,80 +49,31 @@ alloc_fd_state(struct event_base *base, evutil_socket_t fd)
struct fd_state *state = malloc(sizeof(struct fd_state));
if (!state)
return NULL;
memset(state, 0, sizeof(*state));

{
int i;
for (i=0;i<16;++i)
assert(state->junk[i] == 0);
}

state->buffer_len = 1024;
state->buffer = malloc(state->buffer_len);

{
int i;
for (i=0;i<16;++i)
assert(state->junk[i] == 0);
}


if (!state->buffer) {
free(state);
return NULL;
}

state->read_event = event_new(base, fd, EV_READ|EV_PERSIST, do_read, state);

{
int i;
for (i=0;i<16;++i)
assert(state->junk[i] == 0);
}


if (!state->read_event) {
free(state->buffer);
free(state);
return NULL;
}
state->write_event =
event_new(base, fd, EV_WRITE|EV_PERSIST, do_write, state);

{
int i;
for (i=0;i<16;++i)
assert(state->junk[i] == 0);
}

if (!state->write_event) {
event_free(state->read_event);
free(state->buffer);
free(state);
return NULL;
}

state->buffer_used = state->n_written = state->write_upto = 0;

{
int i;
for (i=0;i<16;++i)
assert(state->junk[i] == 0);
}

puts("newstate");
assert(state->write_event);
return state;
}

void
free_fd_state(struct fd_state *state)
{
puts("freestate");
event_free(state->read_event);
event_free(state->write_event);
free(state->buffer);
memset(state, 0, sizeof(*state));
free(state);
}

Expand All @@ -139,24 +90,9 @@ do_read(evutil_socket_t fd, short events, void *arg)
if (result <= 0)
break;

if (state->buffer_used + result >= state->buffer_len) {
char *newbuf;
size_t newlen = state->buffer_len;
do {
newlen *= 2;
} while (newlen < state->buffer_used + result);
newbuf = realloc(state->buffer, newlen);
if (newbuf == NULL) {
perror("realloc");
result = -1;
break;
}
state->buffer = newbuf;
state->buffer_len = newlen;
}

for (i=0; i < result; ++i) {
state->buffer[state->buffer_used++] = rot13_char(buf[i]);
if (state->buffer_used < sizeof(state->buffer))
state->buffer[state->buffer_used++] = rot13_char(buf[i]);
if (buf[i] == '\n') {
assert(state->write_event);
event_add(state->write_event, NULL);
Expand Down
30 changes: 5 additions & 25 deletions examples_01/01_rot13_server_select.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <stdio.h>
#include <errno.h>

#define MAX_LINE 16384

char
rot13_char(char c)
{
Expand All @@ -28,8 +30,7 @@ rot13_char(char c)
}

struct fd_state {
char *buffer;
size_t buffer_len;
char buffer[MAX_LINE];
size_t buffer_used;

int writing;
Expand All @@ -43,12 +44,6 @@ alloc_fd_state(void)
struct fd_state *state = malloc(sizeof(struct fd_state));
if (!state)
return NULL;
state->buffer_len = 1024;
state->buffer = malloc(state->buffer_len);
if (!state->buffer) {
free(state);
return NULL;
}
state->buffer_used = state->n_written = state->writing =
state->write_upto = 0;
return state;
Expand All @@ -57,7 +52,6 @@ alloc_fd_state(void)
void
free_fd_state(struct fd_state *state)
{
free(state->buffer);
free(state);
}

Expand All @@ -77,24 +71,10 @@ do_read(int fd, struct fd_state *state)
result = recv(fd, buf, sizeof(buf), 0);
if (result <= 0)
break;
if (state->buffer_used + result >= state->buffer_len) {
char *newbuf;
size_t newlen = state->buffer_len;
do {
newlen *= 2;
} while (newlen < state->buffer_used + result);
newbuf = realloc(state->buffer, newlen);
if (newbuf == NULL) {
perror("realloc");
result = -1;
break;
}
state->buffer = newbuf;
state->buffer_len = newlen;
}

for (i=0; i < result; ++i) {
state->buffer[state->buffer_used++] = rot13_char(buf[i]);
if (state->buffer_used < sizeof(state->buffer))
state->buffer[state->buffer_used++] = rot13_char(buf[i]);
if (buf[i] == '\n') {
state->writing = 1;
state->write_upto = state->buffer_used;
Expand Down

0 comments on commit 758f12f

Please sign in to comment.