Skip to content

Commit bf6c15e

Browse files
authored
add curl fuzzer (#18)
1 parent df2f60b commit bf6c15e

File tree

6 files changed

+228
-0
lines changed

6 files changed

+228
-0
lines changed

curl/Dockerfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2016 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
################################################################################
16+
17+
FROM ossfuzz/base-libfuzzer
18+
MAINTAINER dvyukov@google.com
19+
RUN apt-get install -y make autoconf automake libtool libssl-dev zlib1g-dev
20+
21+
COPY build.sh fuzzer.cc /src/
22+
23+
ENV GIT_URL ""

curl/Jenkinsfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2016 Google Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
////////////////////////////////////////////////////////////////////////////////
16+
17+
def libfuzzerBuild = fileLoader.fromGit('infra/libfuzzer-pipeline.groovy',
18+
'https://github.com/google/oss-fuzz.git')
19+
20+
libfuzzerBuild {
21+
git = "https://github.com/curl/curl.git"
22+
}

curl/build.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash -eu
2+
# Copyright 2016 Google Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
################################################################################
17+
18+
cd /src/curl
19+
./buildconf
20+
./configure --disable-shared --enable-debug --enable-maintainer-mode --disable-symbol-hiding --disable-threaded-resolver --enable-ipv6 --with-random=/dev/null
21+
make -j4
22+
$CXX $CXXFLAGS /src/fuzzer.cc -Iinclude lib/.libs/libcurl.a -lssl -lcrypto -lz /work/libfuzzer/*.o -o /out/curl_fuzzer $LDFLAGS

curl/fuzzer.cc

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
# Copyright 2016 Google Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
################################################################################
17+
*/
18+
19+
#include <errno.h>
20+
#include <fcntl.h>
21+
#include <netinet/in.h>
22+
#include <stddef.h>
23+
#include <stdint.h>
24+
#include <stdio.h>
25+
#include <stdlib.h>
26+
#include <string.h>
27+
#include <sys/select.h>
28+
#include <sys/socket.h>
29+
#include <sys/stat.h>
30+
#include <sys/time.h>
31+
#include <sys/types.h>
32+
#include <unistd.h>
33+
34+
#include <curl/curl.h>
35+
36+
static const void *cur_data;
37+
static int cur_size = -1;
38+
static int server_fd = -1;
39+
static int client_fd = -1;
40+
static bool wrote = false;
41+
42+
static void fail(const char *why) {
43+
perror(why);
44+
exit(1);
45+
}
46+
47+
static curl_socket_t open_sock(void *ctx, curlsocktype purpose,
48+
struct curl_sockaddr *address) {
49+
if (cur_size == -1) fail("not fuzzing");
50+
if (server_fd != -1 || client_fd != -1) fail("already connected");
51+
int fds[2];
52+
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) fail("socketpair");
53+
server_fd = fds[0];
54+
client_fd = fds[1];
55+
if (write(server_fd, cur_data, cur_size) != cur_size) fail("write");
56+
if (shutdown(server_fd, SHUT_WR)) fail("shutdown");
57+
return client_fd;
58+
}
59+
60+
static int set_opt(void *ctx, curl_socket_t curlfd, curlsocktype purpose) {
61+
return CURL_SOCKOPT_ALREADY_CONNECTED;
62+
}
63+
64+
static size_t write_callback(char *ptr, size_t size, size_t n, void *ctx) {
65+
return size * n;
66+
}
67+
68+
static size_t read_callback(char *buf, size_t size, size_t n, void *ctx) {
69+
if (wrote || size * n == 0) return 0;
70+
wrote = true;
71+
buf[0] = 'a';
72+
return 1;
73+
}
74+
75+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
76+
cur_data = Data;
77+
cur_size = Size;
78+
wrote = false;
79+
CURL *curl = curl_easy_init();
80+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
81+
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
82+
curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, open_sock);
83+
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, set_opt);
84+
#if defined(FUZZER_FTP)
85+
curl_easy_setopt(curl, CURLOPT_URL, "ftp://user@localhost/file.txt");
86+
#elif defined(FUZZER_IMAP)
87+
curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
88+
curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret");
89+
curl_easy_setopt(curl, CURLOPT_URL, "imap://localhost");
90+
#elif defined(FUZZER_POP3)
91+
curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
92+
curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret");
93+
curl_easy_setopt(curl, CURLOPT_URL, "pop3://localhost");
94+
#elif defined(FUZZER_HTTP_UPLOAD)
95+
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/");
96+
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
97+
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
98+
#elif defined(FUZZER_HTTP2)
99+
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/");
100+
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
101+
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
102+
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
103+
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 0L);
104+
#else
105+
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/");
106+
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
107+
#endif
108+
curl_easy_perform(curl);
109+
curl_easy_cleanup(curl);
110+
close(server_fd);
111+
close(client_fd);
112+
server_fd = -1;
113+
client_fd = -1;
114+
cur_data = NULL;
115+
cur_size = -1;
116+
return 0;
117+
}

curl/http.dict

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"\x0a\x0d"
2+
"HTTP/1.0"
3+
"HTTP/1.1"
4+
"100"
5+
"200"
6+
"301"
7+
"400"
8+
"Server:"
9+
"Last-Modified:"
10+
"Content-Type:"
11+
"text/html"
12+
"charset=UTF-8"
13+
"Accept-Ranges:"
14+
"bytes"
15+
"Content-Length:"
16+
"Transfer-Encoding:"
17+
"compress"
18+
"exi"
19+
"gzip"
20+
"identity"
21+
"pack200-gzip"
22+
"br"
23+
"deflate"
24+
"bzip2"
25+
"lzma"
26+
"xz"
27+
"Content-Encoding:"
28+
"chunked"
29+
"Connection:"
30+
"close"
31+
"Date:"
32+
"Expires:"
33+
"Fri, 31 Dec 1999 23:59:59 GMT"
34+
"Cache-Control:"
35+
"no-cache"
36+
"no-store"
37+
"must-revalidate"
38+
"Pragma:"
39+
"no-cache"
40+
"Host:"
41+

curl/http.options

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[libfuzzer]
2+
max_len = 1000
3+
dict = http.dict

0 commit comments

Comments
 (0)