summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-04-14 09:46:39 +0300
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-04-14 09:46:39 +0300
commitd2063ff0b63b3b4f2f2081e61874a3c2487c4994 (patch)
treead094fd84b4fa329a02cb0be5ddf9198329f0643
parent9939910833a9289b5913eff29f951195e7bc61c6 (diff)
Handle unterminated strings when encoding.
If the null terminator is not present, string will be limited to the data size of the field. If you are still using the pb_enc_string (deprecated since 0.1.3) from callbacks, now would be an excellent time to stop. The pb_field_t for the callback will not contain proper data_size. Use pb_encode_string() instead. Update issue 68 Status: FixedInGit
-rw-r--r--pb_encode.c12
-rw-r--r--tests/encode_unittests.c8
-rw-r--r--tests/unittestproto.proto4
3 files changed, 19 insertions, 5 deletions
diff --git a/pb_encode.c b/pb_encode.c
index 48a3c950..0e048ac6 100644
--- a/pb_encode.c
+++ b/pb_encode.c
@@ -461,8 +461,16 @@ bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, con
bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{
- UNUSED(field);
- return pb_encode_string(stream, (const uint8_t*)src, strlen((const char*)src));
+ /* strnlen() is not always available, so just use a for-loop */
+ size_t size = 0;
+ const char *p = (const char*)src;
+ while (size < field->data_size && *p != '\0')
+ {
+ size++;
+ p++;
+ }
+
+ return pb_encode_string(stream, (const uint8_t*)src, size);
}
bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
diff --git a/tests/encode_unittests.c b/tests/encode_unittests.c
index 3078998e..6a8f5e9e 100644
--- a/tests/encode_unittests.c
+++ b/tests/encode_unittests.c
@@ -180,12 +180,14 @@ int main()
{
uint8_t buffer[30];
pb_ostream_t s;
- char value[] = "xyzzy";
+ char value[30] = "xyzzy";
COMMENT("Test pb_enc_string")
- TEST(WRITES(pb_enc_string(&s, NULL, &value), "\x05xyzzy"))
+ TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x05xyzzy"))
value[0] = '\0';
- TEST(WRITES(pb_enc_string(&s, NULL, &value), "\x00"))
+ TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x00"))
+ memset(value, 'x', 30);
+ TEST(WRITES(pb_enc_string(&s, &StringMessage_fields[0], &value), "\x0Axxxxxxxxxx"))
}
{
diff --git a/tests/unittestproto.proto b/tests/unittestproto.proto
index c8a39dd6..7024942e 100644
--- a/tests/unittestproto.proto
+++ b/tests/unittestproto.proto
@@ -8,6 +8,10 @@ message FloatArray {
repeated float data = 1 [(nanopb).max_count = 10];
}
+message StringMessage {
+ required string data = 1 [(nanopb).max_size = 10];
+}
+
message CallbackArray {
// We cheat a bit and use this message for testing other types, too.
// Nanopb does not care about the actual defined data type for callback