Skip to content

Commit

Permalink
Merge pull request Wilfred#3 from tree-sitter/fuzzer-fixes
Browse files Browse the repository at this point in the history
Fix bugs found during fuzzing
  • Loading branch information
Max Brunsfeld authored Aug 29, 2018
2 parents fa5426a + 461343b commit e7b12d1
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 28 deletions.
15 changes: 2 additions & 13 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,10 @@ language: node_js

sudo: false

node_js:
- "node"

compiler: clang-3.6
node_js: node

env:
- CXX=clang-3.6

addons:
apt:
sources:
- llvm-toolchain-precise-3.6
- ubuntu-toolchain-r-test
packages:
- clang-3.6
- CXX=clang

branches:
only:
Expand Down
41 changes: 27 additions & 14 deletions src/scanner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ struct Scanner {
Scanner() {}

unsigned serialize(char *buffer) {
unsigned i = 0;
unsigned n = tags.size();
std::memcpy(buffer, &n, sizeof(n));
i += sizeof(n);
for (unsigned j = 0; j < n; j++) {
Tag &tag = tags[j];
uint16_t tag_count = tags.size() > UINT16_MAX ? UINT16_MAX : tags.size();
uint16_t serialized_tag_count = 0;

unsigned i = sizeof(tag_count);
std::memcpy(&buffer[i], &tag_count, sizeof(tag_count));
i += sizeof(tag_count);

for (; serialized_tag_count < tag_count; serialized_tag_count++) {
Tag &tag = tags[serialized_tag_count];
if (tag.type == CUSTOM) {
unsigned name_length = tag.custom_tag_name.size();
if (name_length > UINT8_MAX) name_length = UINT8_MAX;
if (i + 2 + name_length >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) break;
buffer[i++] = static_cast<char>(tag.type);
buffer[i++] = name_length;
Expand All @@ -44,22 +48,29 @@ struct Scanner {
buffer[i++] = static_cast<char>(tag.type);
}
}

std::memcpy(&buffer[0], &serialized_tag_count, sizeof(serialized_tag_count));
return i;
}

void deserialize(const char *buffer, unsigned length) {
tags.clear();
if (length > 0) {
unsigned i = 0;
unsigned n;
std::memcpy(&n, buffer, sizeof(n));
i += sizeof(n);
tags.resize(n);
for (unsigned j = 0; j < n; j++) {
uint16_t tag_count, serialized_tag_count;

std::memcpy(&serialized_tag_count, &buffer[i], sizeof(serialized_tag_count));
i += sizeof(serialized_tag_count);

std::memcpy(&tag_count, &buffer[i], sizeof(tag_count));
i += sizeof(tag_count);

tags.resize(tag_count);
for (unsigned j = 0; j < serialized_tag_count; j++) {
Tag &tag = tags[j];
tag.type = static_cast<TagType>(buffer[i++]);
if (tag.type == CUSTOM) {
unsigned name_length = buffer[i++];
uint16_t name_length = (uint16_t)buffer[i++];
tag.custom_tag_name.assign(&buffer[i], &buffer[i + name_length]);
i += name_length;
}
Expand Down Expand Up @@ -202,8 +213,10 @@ struct Scanner {
lexer->advance(lexer, false);
if (lexer->lookahead == '>') {
lexer->advance(lexer, false);
tags.pop_back();
lexer->result_symbol = SELF_CLOSING_TAG_DELIMITER;
if (!tags.empty()) {
tags.pop_back();
lexer->result_symbol = SELF_CLOSING_TAG_DELIMITER;
}
return true;
}
return false;
Expand Down
8 changes: 7 additions & 1 deletion src/tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,13 @@ struct Tag {
TagType type;
string custom_tag_name;

Tag() : type(DIV) {}
// This default constructor is used in the case where there is not enough space
// in the serialization buffer to store all of the tags. In that case, tags
// that cannot be serialized will be treated as having an unknown type. These
// tags will be closed via implicit end tags regardless of the next closing
// tag is encountered.
Tag() : type(END_OF_VOID_TAGS) {}

Tag(TagType type, const string &name) : type(type), custom_tag_name(name) {}

bool operator==(const Tag &other) const {
Expand Down

0 comments on commit e7b12d1

Please sign in to comment.