Merge pull request #465 from prusnak/validate-utf8
Introduce new compile time flag: PB_VALIDATE_UTF8
diff --git a/extra/nanopb.mk b/extra/nanopb.mk
index 5c2cff5..16bc376 100644
--- a/extra/nanopb.mk
+++ b/extra/nanopb.mk
@@ -23,10 +23,11 @@
PROTOC_OPTS =
else
# Source only or git checkout
- PROTOC = protoc
ifdef WINDOWS
- PROTOC_OPTS = --plugin=protoc-gen-nanopb=$(NANOPB_DIR)/generator/protoc-gen-nanopb.bat
+ PROTOC = "python $(NANOPB_DIR)/generator/protoc"
+ PROTOC_OPTS = --plugin=protoc-gen-nanopb=$(NANOPB_DIR)/generator/protoc-gen-nanopb.bat
else
+ PROTOC = $(NANOPB_DIR)/generator/protoc
PROTOC_OPTS = --plugin=protoc-gen-nanopb=$(NANOPB_DIR)/generator/protoc-gen-nanopb
endif
endif
diff --git a/extra/poetry/pyproject.toml b/extra/poetry/pyproject.toml
index cc1a5bd..5b33dfe 100644
--- a/extra/poetry/pyproject.toml
+++ b/extra/poetry/pyproject.toml
@@ -18,9 +18,13 @@
[tool.poetry.dependencies]
python = ">=2.7"
protobuf = ">=3.6"
+grpcio-tools = {version = ">=1.26.0rc1", allow-prereleases = true, optional=true}
[tool.poetry.dev-dependencies]
+[tool.poetry.extras]
+grpcio-tools = ["grpcio-tools"]
+
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index 87802cd..d14860d 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -10,6 +10,8 @@
import re
import codecs
import copy
+import tempfile
+import os
from functools import reduce
try:
@@ -38,6 +40,7 @@
try:
from .proto import nanopb_pb2
+ from .proto._utils import invoke_protoc
except TypeError:
sys.stderr.write('''
****************************************************************************
@@ -58,6 +61,7 @@
except (ValueError, SystemError):
# Probably invoked directly instead of via installed scripts.
import proto.nanopb_pb2 as nanopb_pb2
+ from proto._utils import invoke_protoc
except:
sys.stderr.write('''
********************************************************************
@@ -1833,9 +1837,31 @@
sys.stderr.write('Google Python protobuf library imported from %s, version %s\n'
% (google.protobuf.__file__, google.protobuf.__version__))
- Globals.verbose_options = options.verbose
+ # Load .pb files into memory and compile any .proto files.
+ fdescs = {}
+ include_path = ['-I%s' % p for p in options.options_path]
for filename in filenames:
- results = process_file(filename, None, options)
+ if filename.endswith(".proto"):
+ with tempfile.NamedTemporaryFile(suffix = ".pb") as tmp:
+ invoke_protoc(["protoc"] + include_path + ['-o' + tmp.name, filename])
+ data = tmp.read()
+ else:
+ data = open(filename, 'rb').read()
+
+ open("debug", "wb").write(data)
+ fdesc = descriptor.FileDescriptorSet.FromString(data).file[0]
+ fdescs[fdesc.name] = fdesc
+
+ # Process any include files first, in order to have them
+ # available as dependencies
+ other_files = {}
+ for fdesc in fdescs.values():
+ other_files[fdesc.name] = parse_file(fdesc.name, fdesc, options)
+
+ # Then generate the headers / sources
+ Globals.verbose_options = options.verbose
+ for fdesc in fdescs.values():
+ results = process_file(fdesc.name, fdesc, options, other_files)
base_dir = options.output_dir or ''
to_write = [
diff --git a/generator/proto/__init__.py b/generator/proto/__init__.py
index 93e7b33..29153d4 100644
--- a/generator/proto/__init__.py
+++ b/generator/proto/__init__.py
@@ -1,9 +1,12 @@
'''This file automatically rebuilds the proto definitions for Python.'''
+from __future__ import absolute_import
-import os
import os.path
import sys
-import subprocess
+
+import pkg_resources
+
+from ._utils import has_grpcio_protoc, invoke_protoc
dirname = os.path.dirname(__file__)
protosrc = os.path.join(dirname, "nanopb.proto")
@@ -12,8 +15,22 @@
if os.path.isfile(protosrc):
src_date = os.path.getmtime(protosrc)
if not os.path.isfile(protodst) or os.path.getmtime(protodst) < src_date:
- cmd = ["protoc", "--python_out=.", "nanopb.proto"]
- status = subprocess.call(cmd, cwd = dirname)
- if status != 0:
- sys.stderr.write("Failed to build nanopb_pb2.py: " + ' '.join(cmd) + "\n")
+ cmd = [
+ "protoc",
+ "--python_out={}".format(dirname),
+ protosrc,
+ "-I={}".format(dirname),
+ ]
+
+ if has_grpcio_protoc():
+ # grpcio-tools has an extra CLI argument
+ # from grpc.tools.protoc __main__ invocation.
+ _builtin_proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
+
+ cmd.append("-I={}".format(_builtin_proto_include))
+ try:
+ invoke_protoc(argv=cmd)
+ except:
+ sys.stderr.write("Failed to build nanopb_pb2.py: " + ' '.join(cmd) + "\n")
+ raise
diff --git a/generator/proto/_utils.py b/generator/proto/_utils.py
new file mode 100644
index 0000000..26e1ccf
--- /dev/null
+++ b/generator/proto/_utils.py
@@ -0,0 +1,29 @@
+import subprocess
+
+def has_grpcio_protoc():
+ # type: () -> bool
+ """ checks if grpcio-tools protoc is installed"""
+
+ try:
+ import grpc_tools.protoc
+ except ImportError:
+ return False
+ return True
+
+
+def invoke_protoc(argv):
+ # type: (list) -> typing.Any
+ """
+ Invoke protoc.
+
+ This routine will use grpcio-provided protoc if it exists,
+ using system-installed protoc as a fallback.
+
+ Args:
+ argv: protoc CLI invocation, first item must be 'protoc'
+ """
+ if has_grpcio_protoc():
+ import grpc_tools.protoc as protoc
+ return protoc.main(argv)
+ else:
+ return subprocess.check_call(argv)
diff --git a/generator/protoc b/generator/protoc
new file mode 100755
index 0000000..15f1d81
--- /dev/null
+++ b/generator/protoc
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+import sys
+from nanopb_generator import invoke_protoc
+
+if __name__ == '__main__':
+ status = invoke_protoc(['protoc'] + sys.argv[1:])
+ sys.exit(status)
diff --git a/tests/SConstruct b/tests/SConstruct
index 6601764..e2e337d 100644
--- a/tests/SConstruct
+++ b/tests/SConstruct
@@ -8,6 +8,11 @@
CXX Name of C++ compiler
CCFLAGS Flags to pass to the C compiler
CXXFLAGS Flags to pass to the C++ compiler
+LINKFLAGS Flags to pass to linker
+LINKLIBS Flags to pass to linker after object files
+PROTOC Path to protoc binary
+PROTOCFLAGS Arguments to pass protoc
+NODEFARGS Do not add the default CCFLAGS
For example, for a clang build, use:
scons CC=clang CXX=clang++
@@ -34,6 +39,11 @@
if 'CXX' in ARGUMENTS: env.Replace(CXX = ARGUMENTS['CXX'])
if 'CCFLAGS' in ARGUMENTS: env.Append(CCFLAGS = ARGUMENTS['CCFLAGS'])
if 'CXXFLAGS' in ARGUMENTS: env.Append(CXXFLAGS = ARGUMENTS['CXXFLAGS'])
+if 'LINKFLAGS' in ARGUMENTS: env.Append(LINKFLAGS = ARGUMENTS['LINKFLAGS'])
+if 'LINKLIBS' in ARGUMENTS: env.Append(LINKLIBS = ARGUMENTS['LINKLIBS'])
+if 'PROTOC' in ARGUMENTS: env.Replace(PROTOC = ARGUMENTS['PROTOC'])
+if 'PROTOCFLAGS' in ARGUMENTS: env.Replace(PROTOCFLAGS = ARGUMENTS['PROTOCFLAGS'])
+if 'NODEFARGS' in ARGUMENTS: env.Replace(NODEFARGS = ARGUMENTS['NODEFARGS'])
# Add the builders defined in site_init.py
add_nanopb_builders(env)
@@ -92,91 +102,97 @@
if status:
conf.env['PROTOC_VERSION'] = output
- # Check if libmudflap is available (only with GCC)
- if 'gcc' in env['CC']:
- if conf.CheckLib('mudflap'):
- conf.env.Append(CCFLAGS = '-fmudflap')
- conf.env.Append(LINKFLAGS = '-fmudflap')
-
- # Check if we can use extra strict warning flags (only with GCC)
- extra = '-Wcast-qual -Wlogical-op -Wconversion'
- extra += ' -fstrict-aliasing -Wstrict-aliasing=1'
- extra += ' -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls'
- extra += ' -Wstack-protector '
- if 'gcc' in env['CC']:
- if conf.CheckCCFLAGS(extra):
- conf.env.Append(CORECFLAGS = extra)
-
- # Check if we can use undefined behaviour sanitizer (only with clang)
- # TODO: Fuzz test triggers the bool sanitizer, figure out whether to
- # modify the fuzz test or to keep ignoring the check.
- extra = '-fsanitize=undefined,integer -fno-sanitize-recover=undefined,integer '
- if 'clang' in env['CC']:
- if conf.CheckCCFLAGS(extra, linkflags = extra):
- conf.env.Append(CORECFLAGS = extra)
- conf.env.Append(LINKFLAGS = extra)
+ if not env.get('NODEFARGS'):
+ # Check if libmudflap is available (only with GCC)
+ if 'gcc' in env['CC']:
+ if conf.CheckLib('mudflap'):
+ conf.env.Append(CCFLAGS = '-fmudflap')
+ conf.env.Append(LINKFLAGS = '-fmudflap')
+
+ # Check if we can use extra strict warning flags (only with GCC)
+ extra = '-Wcast-qual -Wlogical-op -Wconversion'
+ extra += ' -fstrict-aliasing -Wstrict-aliasing=1'
+ extra += ' -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls'
+ extra += ' -Wstack-protector '
+ if 'gcc' in env['CC']:
+ if conf.CheckCCFLAGS(extra):
+ conf.env.Append(CORECFLAGS = extra)
+
+ # Check if we can use undefined behaviour sanitizer (only with clang)
+ # TODO: Fuzz test triggers the bool sanitizer, figure out whether to
+ # modify the fuzz test or to keep ignoring the check.
+ extra = '-fsanitize=undefined,integer -fno-sanitize-recover=undefined,integer '
+ if 'clang' in env['CC']:
+ if conf.CheckCCFLAGS(extra, linkflags = extra):
+ conf.env.Append(CORECFLAGS = extra)
+ conf.env.Append(LINKFLAGS = extra)
# End the config stuff
env = conf.Finish()
-# Initialize the CCFLAGS according to the compiler
-if 'gcc' in env['CC']:
- # GNU Compiler Collection
-
- # Debug info, warnings as errors
- env.Append(CFLAGS = '-g -Wall -Werror ')
- env.Append(CORECFLAGS = '-Wextra')
-
- # Pedantic ANSI C. On AVR this doesn't work because we use large
- # enums in some of the tests.
- if env.get("EMBEDDED") != "AVR":
- env.Append(CFLAGS = '-ansi -pedantic')
-
- # Profiling and coverage
- if not env.get("EMBEDDED"):
- env.Append(CFLAGS = '-fprofile-arcs -ftest-coverage ')
- env.Append(LINKFLAGS = '-g --coverage')
+if not env.get('NODEFARGS'):
+ # Initialize the CCFLAGS according to the compiler
+ if 'gcc' in env['CC']:
+ # GNU Compiler Collection
-
- # We currently need uint64_t anyway, even though ANSI C90 otherwise..
- env.Append(CFLAGS = '-Wno-long-long')
-elif 'clang' in env['CC']:
- # CLang
- env.Append(CFLAGS = '-ansi -g -Wall -Werror')
- env.Append(CORECFLAGS = ' -Wextra -Wcast-qual -Wconversion')
-elif 'cl' in env['CC']:
- # Microsoft Visual C++
-
- # Debug info on, warning level 2 for tests, warnings as errors
- env.Append(CFLAGS = '/Zi /W2 /WX')
- env.Append(LINKFLAGS = '/DEBUG')
-
- # More strict checks on the nanopb core
- env.Append(CORECFLAGS = '/W4')
+ # Debug info, warnings as errors
+ env.Append(CFLAGS = '-g -Wall -Werror ')
+ env.Append(CORECFLAGS = '-Wextra')
- # Disable warning about sizeof(union{}) construct that is used in
- # message size macros, in e.g. multiple_files testcase. The C construct
- # itself is valid, but quite rare, which causes Visual C++ to give a warning
- # about it.
- env.Append(CFLAGS = '/wd4116')
-elif 'tcc' in env['CC']:
- # Tiny C Compiler
- env.Append(CFLAGS = '-Wall -Werror -g')
+ # Pedantic ANSI C. On AVR this doesn't work because we use large
+ # enums in some of the tests.
+ if env.get("EMBEDDED") != "AVR":
+ env.Append(CFLAGS = '-ansi -pedantic')
+
+ # Profiling and coverage
+ if not env.get("EMBEDDED"):
+ env.Append(CFLAGS = '-fprofile-arcs -ftest-coverage ')
+ env.Append(LINKFLAGS = '-g --coverage')
+
+
+ # We currently need uint64_t anyway, even though ANSI C90 otherwise..
+ env.Append(CFLAGS = '-Wno-long-long')
+ elif 'clang' in env['CC']:
+ # CLang
+ env.Append(CFLAGS = '-ansi -g -Wall -Werror')
+ env.Append(CORECFLAGS = ' -Wextra -Wcast-qual -Wconversion')
+ elif 'cl' in env['CC']:
+ # Microsoft Visual C++
+
+ # Debug info on, warning level 2 for tests, warnings as errors
+ env.Append(CFLAGS = '/Zi /W2 /WX')
+ env.Append(LINKFLAGS = '/DEBUG')
+
+ # More strict checks on the nanopb core
+ env.Append(CORECFLAGS = '/W4')
+
+ # Disable warning about sizeof(union{}) construct that is used in
+ # message size macros, in e.g. multiple_files testcase. The C construct
+ # itself is valid, but quite rare, which causes Visual C++ to give a warning
+ # about it.
+ env.Append(CFLAGS = '/wd4116')
+ elif 'tcc' in env['CC']:
+ # Tiny C Compiler
+ env.Append(CFLAGS = '-Wall -Werror -g')
+
+ if 'clang' in env['CXX']:
+ env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
+ elif 'g++' in env['CXX'] or 'gcc' in env['CXX']:
+ env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
+ elif 'cl' in env['CXX']:
+ env.Append(CXXFLAGS = '/Zi /W2 /WX /wd4116 /wd4127')
env.SetDefault(CORECFLAGS = '')
-if 'clang' in env['CXX']:
- env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
-elif 'g++' in env['CXX'] or 'gcc' in env['CXX']:
- env.Append(CXXFLAGS = '-g -Wall -Werror -Wextra -Wno-missing-field-initializers')
-elif 'cl' in env['CXX']:
- env.Append(CXXFLAGS = '/Zi /W2 /WX /wd4116 /wd4127')
-
if not env.get("EMBEDDED"):
valgrind = env.WhereIs('valgrind')
if valgrind:
env.SetDefault(VALGRIND = valgrind)
+# Make it possible to add commands to the end of linker line
+env.SetDefault(LINKLIBS = '')
+env.Replace(LINKCOM = env['LINKCOM'] + " $LINKLIBS")
+
# Now include the SConscript files from all subdirectories
import os.path
env['VARIANT_DIR'] = 'build'
diff --git a/tests/float_double_conversion/SConscript b/tests/float_double_conversion/SConscript
index f64a318..21c9a81 100644
--- a/tests/float_double_conversion/SConscript
+++ b/tests/float_double_conversion/SConscript
@@ -6,6 +6,9 @@
opts = env.Clone()
opts.Append(CPPDEFINES = {'PB_CONVERT_DOUBLE_FLOAT': 1})
+if opts.get('EMBEDDED') == 'AVR':
+ opts.Append(CFLAGS = "-Wno-overflow")
+
# Build new version of core
strict = opts.Clone()
strict.Append(CFLAGS = strict['CORECFLAGS'])
diff --git a/tests/float_double_conversion/float_double_conversion.c b/tests/float_double_conversion/float_double_conversion.c
index eb3b45a..70a3664 100644
--- a/tests/float_double_conversion/float_double_conversion.c
+++ b/tests/float_double_conversion/float_double_conversion.c
@@ -17,7 +17,9 @@
static const double testvalues[] = {
0.0, -0.0, 0.1, -0.1,
M_PI, -M_PI, 123456.789, -123456.789,
+#if defined(NAN) && defined(INFINITY)
INFINITY, -INFINITY, NAN, INFINITY - INFINITY,
+#endif
1e38, -1e38, 1e39, -1e39,
1e-38, -1e-38, 1e-39, -1e-39,
3.14159e-37,-3.14159e-37, 3.14159e-43, -3.14159e-43,
diff --git a/tests/fuzztest/SConscript b/tests/fuzztest/SConscript
index 52033e1..7723d99 100644
--- a/tests/fuzztest/SConscript
+++ b/tests/fuzztest/SConscript
@@ -36,14 +36,6 @@
iterations = 10000
env.RunTest(fuzz, ARGS = [str(seed), str(iterations)])
-fuzzstub = malloc_env.Program(["fuzzstub.c",
- "alltypes_pointer.pb.c",
- "alltypes_static.pb.c",
- "$COMMON/pb_encode_with_malloc.o",
- "$COMMON/pb_decode_with_malloc.o",
- "$COMMON/pb_common_with_malloc.o",
- "$COMMON/malloc_wrappers.o"])
-
generate_message = malloc_env.Program(["generate_message.c",
"alltypes_static.pb.c",
"$COMMON/pb_encode.o",
diff --git a/tests/fuzztest/fuzzstub.c b/tests/fuzztest/fuzzstub.c
deleted file mode 100644
index ec9e2af..0000000
--- a/tests/fuzztest/fuzzstub.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Fuzz testing for the nanopb core.
- * This can be used with external fuzzers, e.g. radamsa.
- * It performs most of the same checks as fuzztest, but does not feature data generation.
- */
-
-#include <pb_decode.h>
-#include <pb_encode.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <malloc_wrappers.h>
-#include "alltypes_static.pb.h"
-#include "alltypes_pointer.pb.h"
-
-#define BUFSIZE 4096
-
-static bool do_static_decode(uint8_t *buffer, size_t msglen, bool assert_success)
-{
- pb_istream_t stream;
- bool status;
-
- alltypes_static_AllTypes *msg = malloc_with_check(sizeof(alltypes_static_AllTypes));
- stream = pb_istream_from_buffer(buffer, msglen);
- status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg);
-
- if (!status && assert_success)
- {
- /* Anything that was successfully encoded, should be decodeable.
- * One exception: strings without null terminator are encoded up
- * to end of buffer, but refused on decode because the terminator
- * would not fit. */
- if (strcmp(stream.errmsg, "string overflow") != 0)
- assert(status);
- }
-
- free_with_check(msg);
- return status;
-}
-
-static bool do_pointer_decode(uint8_t *buffer, size_t msglen, bool assert_success)
-{
- pb_istream_t stream;
- bool status;
- alltypes_pointer_AllTypes *msg;
-
- msg = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
- memset(msg, 0, sizeof(alltypes_pointer_AllTypes));
- stream = pb_istream_from_buffer(buffer, msglen);
-
- assert(get_alloc_count() == 0);
- status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg);
-
- if (assert_success)
- assert(status);
-
- pb_release(alltypes_pointer_AllTypes_fields, msg);
- assert(get_alloc_count() == 0);
-
- free_with_check(msg);
-
- return status;
-}
-
-/* Do a decode -> encode -> decode -> encode roundtrip */
-static void do_static_roundtrip(uint8_t *buffer, size_t msglen)
-{
- bool status;
- uint8_t *buf2 = malloc_with_check(BUFSIZE);
- uint8_t *buf3 = malloc_with_check(BUFSIZE);
- size_t msglen2, msglen3;
- alltypes_static_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_static_AllTypes));
- alltypes_static_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_static_AllTypes));
- memset(msg1, 0, sizeof(alltypes_static_AllTypes));
- memset(msg2, 0, sizeof(alltypes_static_AllTypes));
-
- {
- pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
- status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg1);
- assert(status);
- }
-
- {
- pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
- status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg1);
- assert(status);
- msglen2 = stream.bytes_written;
- }
-
- {
- pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
- status = pb_decode(&stream, alltypes_static_AllTypes_fields, msg2);
- assert(status);
- }
-
- {
- pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
- status = pb_encode(&stream, alltypes_static_AllTypes_fields, msg2);
- assert(status);
- msglen3 = stream.bytes_written;
- }
-
- assert(msglen2 == msglen3);
- assert(memcmp(buf2, buf3, msglen2) == 0);
-
- free_with_check(msg1);
- free_with_check(msg2);
- free_with_check(buf2);
- free_with_check(buf3);
-}
-
-/* Do decode -> encode -> decode -> encode roundtrip */
-static void do_pointer_roundtrip(uint8_t *buffer, size_t msglen)
-{
- bool status;
- uint8_t *buf2 = malloc_with_check(BUFSIZE);
- uint8_t *buf3 = malloc_with_check(BUFSIZE);
- size_t msglen2, msglen3;
- alltypes_pointer_AllTypes *msg1 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
- alltypes_pointer_AllTypes *msg2 = malloc_with_check(sizeof(alltypes_pointer_AllTypes));
- memset(msg1, 0, sizeof(alltypes_pointer_AllTypes));
- memset(msg2, 0, sizeof(alltypes_pointer_AllTypes));
-
- {
- pb_istream_t stream = pb_istream_from_buffer(buffer, msglen);
- status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg1);
- assert(status);
- }
-
- {
- pb_ostream_t stream = pb_ostream_from_buffer(buf2, BUFSIZE);
- status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg1);
- assert(status);
- msglen2 = stream.bytes_written;
- }
-
- {
- pb_istream_t stream = pb_istream_from_buffer(buf2, msglen2);
- status = pb_decode(&stream, alltypes_pointer_AllTypes_fields, msg2);
- assert(status);
- }
-
- {
- pb_ostream_t stream = pb_ostream_from_buffer(buf3, BUFSIZE);
- status = pb_encode(&stream, alltypes_pointer_AllTypes_fields, msg2);
- assert(status);
- msglen3 = stream.bytes_written;
- }
-
- assert(msglen2 == msglen3);
- assert(memcmp(buf2, buf3, msglen2) == 0);
-
- pb_release(alltypes_pointer_AllTypes_fields, msg1);
- pb_release(alltypes_pointer_AllTypes_fields, msg2);
- free_with_check(msg1);
- free_with_check(msg2);
- free_with_check(buf2);
- free_with_check(buf3);
-}
-
-static void run_iteration()
-{
- uint8_t *buffer = malloc_with_check(BUFSIZE);
- size_t msglen;
- bool status;
-
- msglen = fread(buffer, 1, BUFSIZE, stdin);
-
- status = do_static_decode(buffer, msglen, false);
-
- if (status)
- do_static_roundtrip(buffer, msglen);
-
- status = do_pointer_decode(buffer, msglen, false);
-
- if (status)
- do_pointer_roundtrip(buffer, msglen);
-
- free_with_check(buffer);
-}
-
-int main(int argc, char **argv)
-{
- run_iteration();
-
- return 0;
-}
-
diff --git a/tests/fuzztest/fuzztest.c b/tests/fuzztest/fuzztest.c
index 7e9ddb7..93065ae 100644
--- a/tests/fuzztest/fuzztest.c
+++ b/tests/fuzztest/fuzztest.c
@@ -8,11 +8,17 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include <time.h>
#include <malloc_wrappers.h>
+#include "test_helpers.h"
#include "alltypes_static.pb.h"
#include "alltypes_pointer.pb.h"
+#ifdef __AVR__
+#define BUFSIZE 2048
+#else
+#define BUFSIZE 4096
+#endif
+
static uint64_t random_seed;
/* Uses xorshift64 here instead of rand() for both speed and
@@ -198,8 +204,6 @@
}
}
-#define BUFSIZE 4096
-
static bool do_static_encode(uint8_t *buffer, size_t *msglen)
{
pb_ostream_t stream;
@@ -444,19 +448,49 @@
assert(get_alloc_count() == 0);
}
+static void run_stub()
+{
+ uint8_t *buffer = malloc_with_check(BUFSIZE);
+ size_t msglen;
+ bool status;
+
+ SET_BINARY_MODE(stdin);
+ msglen = fread(buffer, 1, BUFSIZE, stdin);
+
+ status = do_static_decode(buffer, msglen, false);
+
+ if (status)
+ do_static_roundtrip(buffer, msglen);
+
+ status = do_pointer_decode(buffer, msglen, false);
+
+ if (status)
+ do_pointer_roundtrip(buffer, msglen);
+
+ free_with_check(buffer);
+}
+
int main(int argc, char **argv)
{
int i;
int iterations;
- random_seed = atol(argv[1]);
- iterations = atol(argv[2]);
- if (iterations == 0) iterations = 10000;
- fprintf(stderr, "Random seed: %u, iterations: %d\n", (unsigned)random_seed, iterations);
-
- for (i = 0; i < iterations; i++)
+ if (argc >= 2)
{
- run_iteration();
+ /* Run in stand-alone mode */
+ random_seed = atol(argv[1]);
+ iterations = (argc >= 3) ? atol(argv[2]) : 10000;
+ fprintf(stderr, "Random seed: %u, iterations: %d\n", (unsigned)random_seed, iterations);
+
+ for (i = 0; i < iterations; i++)
+ {
+ run_iteration();
+ }
+ }
+ else
+ {
+ /* Run as a stub for afl-fuzz and similar */
+ run_stub();
}
return 0;
diff --git a/tests/fuzztest/generate_message.c b/tests/fuzztest/generate_message.c
index 73959fe..4c21a02 100644
--- a/tests/fuzztest/generate_message.c
+++ b/tests/fuzztest/generate_message.c
@@ -8,7 +8,6 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include <time.h>
#include "alltypes_static.pb.h"
static uint64_t random_seed;
@@ -66,7 +65,7 @@
static void generate_message()
{
alltypes_static_AllTypes msg;
- uint8_t buf[8192];
+ uint8_t buf[4096];
pb_ostream_t stream = {0};
do {
@@ -83,16 +82,15 @@
int main(int argc, char **argv)
{
- if (argc > 1)
+ if (argc < 2)
{
- random_seed = atol(argv[1]);
+ fprintf(stderr, "Usage: generate_message <seed>\n");
+ return 1;
}
- else
- {
- random_seed = time(NULL);
- }
-
- fprintf(stderr, "Random seed: %llu\n", (long long unsigned)random_seed);
+
+ random_seed = atol(argv[1]);
+
+ fprintf(stderr, "Random seed: %u\n", (unsigned)random_seed);
generate_message();
diff --git a/tests/fuzztest/run_radamsa.sh b/tests/fuzztest/run_radamsa.sh
deleted file mode 100755
index 52cd40a..0000000
--- a/tests/fuzztest/run_radamsa.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-TMP=`tempfile`
-
-echo $TMP
-while true
-do
- radamsa sample_data/* > $TMP
- $1 < $TMP
- test $? -gt 127 && break
-done
-
diff --git a/tests/site_scons/site_tools/nanopb.py b/tests/site_scons/site_tools/nanopb.py
index 409d86c..f0626c6 100644
--- a/tests/site_scons/site_tools/nanopb.py
+++ b/tests/site_scons/site_tools/nanopb.py
@@ -64,6 +64,11 @@
# Use protoc bundled with binary package
return env['ESCAPE'](p1)
+ p = os.path.join(n, 'generator', 'protoc')
+ if os.path.exists(p):
+ # Use the grcpio-tools protoc wrapper
+ return env['ESCAPE'](p)
+
p = env.WhereIs('protoc')
if p:
# Use protoc from path