Author: rhuijben Date: Wed Nov 11 13:16:46 2015 New Revision: 1713834 URL: http://svn.apache.org/viewvc?rev=1713834&view=rev Log: Extend the linebuf crlf test to show that we have a huge problem with some bucket types. I really hope that nobody encountered this in the real world.
I have no proper solution to solve this problem yet, but I can imagine seeing this problem in certain cases where we didn't implement peek yet. * buckets/buckets.c (serf_linebuf_fetch): Note problem (twice). * test/test_buckets.c (test_linebuf_fetch_crlf): Extend regression test to trigger this problem. Modified: serf/trunk/buckets/buckets.c serf/trunk/test/test_buckets.c Modified: serf/trunk/buckets/buckets.c URL: http://svn.apache.org/viewvc/serf/trunk/buckets/buckets.c?rev=1713834&r1=1713833&r2=1713834&view=diff ============================================================================== --- serf/trunk/buckets/buckets.c (original) +++ serf/trunk/buckets/buckets.c Wed Nov 11 13:16:46 2015 @@ -703,6 +703,10 @@ apr_status_t serf_linebuf_fetch( * split CRLF. */ + /* ### We can't assume peek will ever return any data! + Just check serf_default_peek() + + ### We would be stuck here forever */ status = serf_bucket_peek(bucket, &data, &len); if (SERF_BUCKET_READ_ERROR(status)) return status; @@ -726,6 +730,11 @@ apr_status_t serf_linebuf_fetch( /* Whatever was read, the line is now ready for use. */ linebuf->state = SERF_LINEBUF_READY; } else { + /* ### We can't assume peek will ever return any data! + Just check serf_default_peek() + + ### We would be stuck here forever */ + /* no data available, try again later. */ return APR_EAGAIN; } Modified: serf/trunk/test/test_buckets.c URL: http://svn.apache.org/viewvc/serf/trunk/test/test_buckets.c?rev=1713834&r1=1713833&r2=1713834&view=diff ============================================================================== --- serf/trunk/test/test_buckets.c (original) +++ serf/trunk/test/test_buckets.c Wed Nov 11 13:16:46 2015 @@ -2003,6 +2003,8 @@ static void test_linebuf_fetch_crlf(CuTe }; serf_bucket_t *bkt; serf_linebuf_t linebuf; + serf_bucket_type_t *unfriendly; + apr_status_t status; serf_bucket_alloc_t *alloc = test__create_bucket_allocator(tc, tb->pool); @@ -2041,6 +2043,52 @@ static void test_linebuf_fetch_crlf(CuTe CuAssertIntEquals(tc, 0, linebuf.used); serf_bucket_destroy(bkt); + + /* And now try again with a less frienly peek implementation */ + bkt = serf_bucket_mock_create(actions, sizeof(actions) / sizeof(actions[0]), + alloc); + + unfriendly = serf_bmemdup(alloc, bkt->type, sizeof(*bkt->type)); + unfriendly->peek = serf_default_peek; /* Unable to peek */ + bkt->type = unfriendly; + + serf_linebuf_init(&linebuf); + CuAssertStrEquals(tc, "", linebuf.line); + CuAssertIntEquals(tc, 0, linebuf.used); + CuAssertIntEquals(tc, SERF_LINEBUF_EMPTY, linebuf.state); + + CuAssertIntEquals(tc, APR_SUCCESS, + serf_linebuf_fetch(&linebuf, bkt, SERF_NEWLINE_CRLF)); + /* We got first line in one call. */ + CuAssertIntEquals(tc, SERF_LINEBUF_READY, linebuf.state); + CuAssertStrEquals(tc, "line1", linebuf.line); + CuAssertIntEquals(tc, 5, linebuf.used); + + /* The second line CR and LF splitted across packets. */ + CuAssertIntEquals(tc, APR_EAGAIN, + serf_linebuf_fetch(&linebuf, bkt, SERF_NEWLINE_CRLF)); + CuAssertIntEquals(tc, SERF_LINEBUF_CRLF_SPLIT, linebuf.state); + + /* This test gets now stuck here, because EAGAIN will be returned forever */ + CuAssertIntEquals(tc, APR_EAGAIN, + serf_linebuf_fetch(&linebuf, bkt, SERF_NEWLINE_CRLF)); + CuAssertIntEquals(tc, SERF_LINEBUF_CRLF_SPLIT, linebuf.state); + +#if 0 + CuAssertIntEquals(tc, SERF_LINEBUF_READY, linebuf.state); + CuAssertIntEquals(tc, 5, linebuf.used); + CuAssertStrnEquals(tc, "line2", 0, linebuf.line); + + /* Last line is empty. */ + CuAssertIntEquals(tc, APR_EOF, + serf_linebuf_fetch(&linebuf, bkt, SERF_NEWLINE_CRLF)); + CuAssertIntEquals(tc, SERF_LINEBUF_READY, linebuf.state); + CuAssertStrEquals(tc, "", linebuf.line); + CuAssertIntEquals(tc, 0, linebuf.used); + + serf_bucket_destroy(bkt); + serf_bucket_mem_free(alloc, unfriendly); +#endif } typedef struct prefix_cb