Merge branch 'es/oss-fuzz'

Backport oss-fuzz tests for us to our codebase.

* es/oss-fuzz:
  fuzz: port fuzz-url-decode-mem from OSS-Fuzz
  fuzz: port fuzz-parse-attr-line from OSS-Fuzz
  fuzz: port fuzz-credential-from-url-gently from OSS-Fuzz
This commit is contained in:
Junio C Hamano
2024-12-13 07:33:41 -08:00
8 changed files with 177 additions and 39 deletions

View File

@@ -2422,9 +2422,12 @@ endif
FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o
FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
FUZZ_OBJS += oss-fuzz/fuzz-config.o
FUZZ_OBJS += oss-fuzz/fuzz-credential-from-url-gently.o
FUZZ_OBJS += oss-fuzz/fuzz-date.o
FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
FUZZ_OBJS += oss-fuzz/fuzz-parse-attr-line.o
FUZZ_OBJS += oss-fuzz/fuzz-url-decode-mem.o
.PHONY: fuzz-objs
fuzz-objs: $(FUZZ_OBJS)

40
attr.c
View File

@@ -259,42 +259,6 @@ const struct git_attr *git_attr(const char *name)
return git_attr_internal(name, strlen(name));
}
/* What does a matched pattern decide? */
struct attr_state {
const struct git_attr *attr;
const char *setto;
};
struct pattern {
const char *pattern;
int patternlen;
int nowildcardlen;
unsigned flags; /* PATTERN_FLAG_* */
};
/*
* One rule, as from a .gitattributes file.
*
* If is_macro is true, then u.attr is a pointer to the git_attr being
* defined.
*
* If is_macro is false, then u.pat is the filename pattern to which the
* rule applies.
*
* In either case, num_attr is the number of attributes affected by
* this rule, and state is an array listing them. The attributes are
* listed as they appear in the file (macros unexpanded).
*/
struct match_attr {
union {
struct pattern pat;
const struct git_attr *attr;
} u;
char is_macro;
size_t num_attr;
struct attr_state state[FLEX_ARRAY];
};
static const char blank[] = " \t\r\n";
/* Flags usable in read_attr() and parse_attr_line() family of functions. */
@@ -353,8 +317,8 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
return ep + strspn(ep, blank);
}
static struct match_attr *parse_attr_line(const char *line, const char *src,
int lineno, unsigned flags)
struct match_attr *parse_attr_line(const char *line, const char *src,
int lineno, unsigned flags)
{
size_t namelen, num_attr, i;
const char *cp, *name, *states;

43
attr.h
View File

@@ -240,4 +240,47 @@ int git_attr_system_is_enabled(void);
extern char *git_attr_tree;
/*
* Exposed for fuzz-testing only.
*/
/* What does a matched pattern decide? */
struct attr_state {
const struct git_attr *attr;
const char *setto;
};
struct pattern {
const char *pattern;
int patternlen;
int nowildcardlen;
unsigned flags; /* PATTERN_FLAG_* */
};
/*
* One rule, as from a .gitattributes file.
*
* If is_macro is true, then u.attr is a pointer to the git_attr being
* defined.
*
* If is_macro is false, then u.pat is the filename pattern to which the
* rule applies.
*
* In either case, num_attr is the number of attributes affected by
* this rule, and state is an array listing them. The attributes are
* listed as they appear in the file (macros unexpanded).
*/
struct match_attr {
union {
struct pattern pat;
const struct git_attr *attr;
} u;
char is_macro;
size_t num_attr;
struct attr_state state[FLEX_ARRAY];
};
struct match_attr *parse_attr_line(const char *line, const char *src,
int lineno, unsigned flags);
#endif /* ATTR_H */

View File

@@ -13,7 +13,18 @@ group "Build fuzzers" make \
LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \
fuzz-all
for fuzzer in commit-graph config date pack-headers pack-idx ; do
fuzzers="
commit-graph
config
credential-from-url-gently
date
pack-headers
pack-idx
parse-attr-line
url-decode-mem
"
for fuzzer in $fuzzers; do
begin_group "fuzz-$fuzzer"
./oss-fuzz/fuzz-$fuzzer -verbosity=0 -runs=1 || exit 1
end_group "fuzz-$fuzzer"

3
oss-fuzz/.gitignore vendored
View File

@@ -1,5 +1,8 @@
fuzz-commit-graph
fuzz-config
fuzz-credential-from-url-gently
fuzz-date
fuzz-pack-headers
fuzz-pack-idx
fuzz-parse-attr-line
fuzz-url-decode-mem

View File

@@ -0,0 +1,32 @@
#include "git-compat-util.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "credential.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct credential c;
char *buf;
buf = malloc(size + 1);
if (!buf)
return 0;
memcpy(buf, data, size);
buf[size] = 0;
// start fuzzing
credential_init(&c);
credential_from_url_gently(&c, buf, 1);
// cleanup
credential_clear(&c);
free(buf);
return 0;
}

View File

@@ -0,0 +1,39 @@
#include "git-compat-util.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "attr.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct match_attr *res;
char *buf;
buf = malloc(size + 1);
if (!buf)
return 0;
memcpy(buf, data, size);
buf[size] = 0;
res = parse_attr_line(buf, "dummy", 0, 0);
if (res) {
int j;
for (j = 0; j < res->num_attr; j++) {
const char *setto = res->state[j].setto;
if (ATTR_TRUE(setto) || ATTR_FALSE(setto) ||
ATTR_UNSET(setto))
;
else
free((char *)setto);
}
free(res);
}
free(buf);
return 0;
}

View File

@@ -0,0 +1,43 @@
#include "git-compat-util.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "url.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char *buf;
char *r;
const char *pbuf;
buf = malloc(size + 1);
if (!buf)
return 0;
memcpy(buf, data, size);
buf[size] = 0;
// start fuzzing
r = url_decode(buf);
free(r);
r = url_percent_decode(buf);
free(r);
pbuf = (const char*) buf;
r = url_decode_parameter_name(&pbuf);
free(r);
pbuf = (const char*) buf;
r = url_decode_parameter_value(&pbuf);
free(r);
// cleanup
free(buf);
return 0;
}