File memcached-1.2.x_garbage_data_dos.patch of Package memcached

This patch contains: d9cd01ede97f4145af9781d448c62a3318952719 and 75cc83685e103bc8ba380a57468c8f04413033f9

From 75cc83685e103bc8ba380a57468c8f04413033f9 Mon Sep 17 00:00:00 2001
From: Trond Norbye <Trond.Norbye@sun.com>
Date: Wed, 28 Oct 2009 11:51:05 +0100
Subject: [PATCH] Issue 102: Piping null to the server will crash it

---
 memcached.c |   31 +++++++++++++++++++++++++++++--
 testapp.c   |   17 +++++++++++++++++
 2 files changed, 46 insertions(+), 2 deletions(-)

Index: memcached.c
===================================================================
--- memcached.c.orig	2010-04-09 13:21:06.000000000 +0200
+++ memcached.c	2010-04-09 13:24:35.605185882 +0200
@@ -1861,8 +1861,27 @@ static int try_read_command(conn *c) {
     if (c->rbytes == 0)
         return 0;
     el = memchr(c->rcurr, '\n', c->rbytes);
-    if (!el)
+    if (!el) {
+        if (c->rbytes > 1024) {
+            /*
+             * We didn't have a '\n' in the first k. This _has_ to be a
+             * large multiget, if not we should just nuke the connection.
+             */
+            char *ptr = c->rcurr;
+            while (*ptr == ' ') { /* ignore leading whitespaces */
+                ++ptr;
+            }
+
+            if (ptr - c->rcurr > 100 ||
+                (strncmp(ptr, "get ", 4) && strncmp(ptr, "gets ", 5))) {
+
+                conn_set_state(c, conn_closing);
+                return 1;
+            }
+        }
+
         return 0;
+    }
     cont = el + 1;
     if ((el - c->rcurr) > 1 && *(el - 1) == '\r') {
         el--;
@@ -1925,11 +1944,17 @@ static int try_read_udp(conn *c) {
  * before reading, move the remaining incomplete fragment of a command
  * (if any) to the beginning of the buffer.
  * return 0 if there's nothing to read on the first read.
+ *
+ * To protect us from someone flooding a connection with bogus data causing
+ * the connection to eat up all available memory, break out and start looking
+ * at the data I've got after a number of reallocs...
+ *
  */
 static int try_read_network(conn *c) {
     int gotdata = 0;
     int res;
 
+    int num_allocs = 0;
     assert(c != NULL);
 
     if (c->rcurr != c->rbuf) {
@@ -1940,6 +1965,10 @@ static int try_read_network(conn *c) {
 
     while (1) {
         if (c->rbytes >= c->rsize) {
+            if (num_allocs == 4) {
+                return gotdata;
+            }
+            ++num_allocs;
             char *new_rbuf = realloc(c->rbuf, c->rsize * 2);
             if (!new_rbuf) {
                 if (settings.verbose > 0)
openSUSE Build Service is sponsored by