You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ja...@apache.org on 2026/10/26 15:02:03 UTC
(mynewt-core) branch master updated (5e3dc5f6c -> cc9cd0c92)
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
from 5e3dc5f6c hw/sensor: Fix argument count checks in sensor shell
new 914abe1e2 libc/baselibc: Fix size overflow check in malloc and realloc
new 0b2fa5ecb libc/baselibc: Fix realloc failure handling
new bcba0985e libc/baselibc: Fix strndup with n larger than string length
new 8e62ae709 libc/baselibc: Fix strnstr length handling
new 880fe222c libc/baselibc: Fix sscanf character set conversion
new 5dc315327 libc/baselibc: Add tests for strndup, strnstr and sscanf
new cc9cd0c92 libc/baselibc: Don't pass sizes larger than INT_MAX to _sbrk
The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
libc/baselibc/selftest/src/baselibc_test.c | 6 ++
libc/baselibc/selftest/src/testcases/string_test.c | 83 ++++++++++++++++++++++
libc/baselibc/src/malloc.c | 7 +-
libc/baselibc/src/realloc.c | 20 ++++--
libc/baselibc/src/strndup.c | 8 +--
libc/baselibc/src/strstr.c | 3 +-
libc/baselibc/src/vsscanf.c | 8 ++-
7 files changed, 119 insertions(+), 16 deletions(-)
create mode 100644 libc/baselibc/selftest/src/testcases/string_test.c
(mynewt-core) 07/07: libc/baselibc: Don't pass sizes larger than INT_MAX to _sbrk
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit cc9cd0c92207b0dd577d8a6dfbe1671deea0f5ec
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Mon Oct 26 10:40:48 2026 +0100
libc/baselibc: Don't pass sizes larger than INT_MAX to _sbrk
_sbrk() takes signed increment, so requests larger than INT_MAX were
passed as negative increments, shrinking the heap instead of failing.
The returned memory was then added to the heap as a huge free block,
corrupting heap metadata and returning invalid pointers or looping
forever in subsequent allocations.
Fail such allocations without calling _sbrk().
Assisted-by: Claude:claude-opus-5-5
---
libc/baselibc/src/malloc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libc/baselibc/src/malloc.c b/libc/baselibc/src/malloc.c
index 909794898..8611de027 100644
--- a/libc/baselibc/src/malloc.c
+++ b/libc/baselibc/src/malloc.c
@@ -4,6 +4,7 @@
* Very simple linked-list based malloc()/free().
*/
+#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
@@ -170,7 +171,8 @@ retry_alloc:
break;
}
}
- if (result == NULL) {
+ /* _sbrk() takes signed increment, larger sizes would shrink the heap */
+ if (result == NULL && size <= INT_MAX) {
more_mem = _sbrk(size);
if (more_mem != (void *)-1) {
add_malloc_block(more_mem, size);
(mynewt-core) 02/07: libc/baselibc: Fix realloc failure handling
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 0b2fa5ecb0e6c2e9620c73a007a07ee927b88829
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Sun Oct 25 23:23:27 2026 +0100
libc/baselibc: Fix realloc failure handling
When memory for a larger block could not be allocated, realloc
returned the original pointer instead of NULL, so the caller assumed
the block was enlarged and could write past it. For too large sizes
realloc freed the original block, while it must be left untouched on
failure.
Return NULL in both cases leaving the original block untouched. When
shrinking, the original block is still returned if allocation of new
block fails, as it is large enough.
Assisted-by: Claude:claude-opus-5-5
---
libc/baselibc/src/realloc.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/libc/baselibc/src/realloc.c b/libc/baselibc/src/realloc.c
index 52e983b0c..e78f4f03e 100644
--- a/libc/baselibc/src/realloc.c
+++ b/libc/baselibc/src/realloc.c
@@ -18,11 +18,16 @@ void *realloc(void *ptr, size_t size)
if (!ptr)
return malloc(size);
- if (size == 0 || size > (SIZE_MAX - 2 * sizeof(struct arena_header))) {
+ if (size == 0) {
free(ptr);
return NULL;
}
+ /* Make sure that adding arena header and rounding up does not wrap,
+ original block is left untouched on failure */
+ if (size > (SIZE_MAX - 2 * sizeof(struct arena_header)))
+ return NULL;
+
/* Add the obligatory arena header, and round up */
size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK;
@@ -40,12 +45,13 @@ void *realloc(void *ptr, size_t size)
oldsize = ah->a.size - sizeof(struct arena_header);
newptr = malloc(size);
- if (newptr) {
- memcpy(newptr, ptr, (size < oldsize) ? size : oldsize);
- free(ptr);
- } else {
- newptr = ptr;
- }
+ if (newptr) {
+ memcpy(newptr, ptr, (size < oldsize) ? size : oldsize);
+ free(ptr);
+ } else if (ah->a.size >= size) {
+ /* Shrinking, current block is still large enough */
+ newptr = ptr;
+ }
return newptr;
}
}
(mynewt-core) 05/07: libc/baselibc: Fix sscanf character set conversion
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 880fe222c6a64864e4235d8014a9202f00dba825
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Sun Oct 25 23:23:27 2026 +0100
libc/baselibc: Fix sscanf character set conversion
Field width was ignored for %[ conversion, so all matching input
characters were stored regardless of buffer size given by width.
Ranges in character set, e.g. %[a-z], started at '-' instead of the
character preceding it and did not include the last character.
Assisted-by: Claude:claude-opus-5-5
---
libc/baselibc/src/vsscanf.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libc/baselibc/src/vsscanf.c b/libc/baselibc/src/vsscanf.c
index ddd3d7e91..bc631fb57 100644
--- a/libc/baselibc/src/vsscanf.c
+++ b/libc/baselibc/src/vsscanf.c
@@ -343,6 +343,7 @@ int vsscanf(const char *buffer, const char *format, va_list ap)
matchinv = 1;
} else {
set_bit(matchmap, (unsigned char)ch);
+ range_start = (unsigned char)ch;
state = st_match;
}
break;
@@ -351,10 +352,11 @@ int vsscanf(const char *buffer, const char *format, va_list ap)
if (ch == ']') {
goto match_run;
} else if (ch == '-') {
- range_start = (unsigned char)ch;
+ /* range_start holds previous character */
state = st_match_range;
} else {
set_bit(matchmap, (unsigned char)ch);
+ range_start = (unsigned char)ch;
}
break;
@@ -365,9 +367,10 @@ int vsscanf(const char *buffer, const char *format, va_list ap)
goto match_run;
} else {
int i;
- for (i = range_start; i < (unsigned char)ch;
+ for (i = range_start; i <= (unsigned char)ch;
i++)
set_bit(matchmap, i);
+ range_start = (unsigned char)ch;
state = st_match;
}
break;
@@ -380,6 +383,7 @@ int vsscanf(const char *buffer, const char *format, va_list ap)
if (sarg)
*sarg++ = uc;
q++;
+ width--;
}
if (q != qq && sarg) {
*sarg = '\0';
(mynewt-core) 03/07: libc/baselibc: Fix strndup with n larger than string length
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit bcba0985e4776695cb660f34ee684c7439a9bc5d
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Sun Oct 25 23:23:27 2026 +0100
libc/baselibc: Fix strndup with n larger than string length
If n was larger than string length, terminating NUL was written at
offset n, past the allocated buffer. Use strnlen() to determine length
of copied string.
Assisted-by: Claude:claude-opus-5-5
---
libc/baselibc/src/strndup.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libc/baselibc/src/strndup.c b/libc/baselibc/src/strndup.c
index 427162fb9..c6067d441 100644
--- a/libc/baselibc/src/strndup.c
+++ b/libc/baselibc/src/strndup.c
@@ -7,13 +7,13 @@
char *strndup(const char *s, size_t n)
{
- int l = n > strlen(s) ? strlen(s) + 1 : n + 1;
- char *d = malloc(l);
+ size_t l = strnlen(s, n);
+ char *d = malloc(l + 1);
if (!d)
return NULL;
-
+
memcpy(d, s, l);
- d[n] = '\0';
+ d[l] = '\0';
return d;
}
(mynewt-core) 04/07: libc/baselibc: Fix strnstr length handling
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 8e62ae70963123312f82a9e45f647e7ef0b3c7d5
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Sun Oct 25 23:23:27 2026 +0100
libc/baselibc: Fix strnstr length handling
strnstr() limited the length of the needle instead of the haystack,
reading len bytes of needle regardless of its length and searching
the whole haystack. Search for the whole needle in at most len
characters of haystack.
Assisted-by: Claude:claude-opus-5-5
---
libc/baselibc/src/strstr.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libc/baselibc/src/strstr.c b/libc/baselibc/src/strstr.c
index 0af23bbfd..f777b3d4e 100644
--- a/libc/baselibc/src/strstr.c
+++ b/libc/baselibc/src/strstr.c
@@ -12,5 +12,6 @@ char *strstr(const char *haystack, const char *needle)
char *strnstr(const char *haystack, const char *needle, size_t len)
{
- return (char *)memmem(haystack, strlen(haystack), needle, len);
+ return (char *)memmem(haystack, strnlen(haystack, len), needle,
+ strlen(needle));
}
(mynewt-core) 06/07: libc/baselibc: Add tests for strndup, strnstr and sscanf
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 5dc31532777ba4ab31f2549bb36adc192d02a65c
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Sun Oct 25 23:23:27 2026 +0100
libc/baselibc: Add tests for strndup, strnstr and sscanf
Verify that strndup() does not write past the allocated buffer when n
is larger than string length, that strnstr() limits the search to len
characters of haystack and that sscanf() %[ conversion honours field
width and includes both ends of a character range. These cover the
bugs fixed in previous commits.
Assisted-by: Claude:claude-opus-5-5
---
libc/baselibc/selftest/src/baselibc_test.c | 6 ++
libc/baselibc/selftest/src/testcases/string_test.c | 83 ++++++++++++++++++++++
2 files changed, 89 insertions(+)
diff --git a/libc/baselibc/selftest/src/baselibc_test.c b/libc/baselibc/selftest/src/baselibc_test.c
index 6fbb6c970..da818c393 100755
--- a/libc/baselibc/selftest/src/baselibc_test.c
+++ b/libc/baselibc/selftest/src/baselibc_test.c
@@ -22,10 +22,16 @@
#include "testutil/testutil.h"
TEST_CASE_DECL(tinyprintf_test)
+TEST_CASE_DECL(strndup_test)
+TEST_CASE_DECL(strnstr_test)
+TEST_CASE_DECL(sscanf_set_test)
TEST_SUITE(baselibc_test_suite)
{
tinyprintf_test();
+ strndup_test();
+ strnstr_test();
+ sscanf_set_test();
}
int
diff --git a/libc/baselibc/selftest/src/testcases/string_test.c b/libc/baselibc/selftest/src/testcases/string_test.c
new file mode 100644
index 000000000..c96aaba37
--- /dev/null
+++ b/libc/baselibc/selftest/src/testcases/string_test.c
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "testutil/testutil.h"
+
+TEST_CASE_SELF(strndup_test)
+{
+ char src[16] = "abc";
+ char *s;
+
+ /* n larger than string length */
+ s = strndup(src, 10);
+ TEST_ASSERT_FATAL(s != NULL);
+ TEST_ASSERT(!strcmp(s, "abc"));
+ free(s);
+
+ /* n smaller than string length */
+ s = strndup("abcdef", 3);
+ TEST_ASSERT_FATAL(s != NULL);
+ TEST_ASSERT(!strcmp(s, "abc"));
+ free(s);
+
+ s = strndup("abc", 0);
+ TEST_ASSERT_FATAL(s != NULL);
+ TEST_ASSERT(!strcmp(s, ""));
+ free(s);
+}
+
+TEST_CASE_SELF(strnstr_test)
+{
+ const char *h = "abcdef";
+
+ TEST_ASSERT(strnstr(h, "cd", 6) == h + 2);
+ TEST_ASSERT(strnstr(h, "cd", 4) == h + 2);
+ /* Needle not fully within first len characters */
+ TEST_ASSERT(strnstr(h, "cd", 3) == NULL);
+ TEST_ASSERT(strnstr(h, "ef", 6) == h + 4);
+}
+
+TEST_CASE_SELF(sscanf_set_test)
+{
+ struct {
+ char buf[4];
+ char guard[8];
+ } s;
+ char buf[16];
+ int rc;
+
+ /* Range includes both ends */
+ rc = sscanf("az-", "%[a-z]", buf);
+ TEST_ASSERT(rc == 1);
+ TEST_ASSERT(!strcmp(buf, "az"));
+
+ /* Trailing '-' is literal */
+ rc = sscanf("a-b", "%[a-]", buf);
+ TEST_ASSERT(rc == 1);
+ TEST_ASSERT(!strcmp(buf, "a-"));
+
+ /* Width limits number of characters stored */
+ memset(&s, 0x5a, sizeof(s));
+ rc = sscanf("123456789", "%3[0-9]", s.buf);
+ TEST_ASSERT(rc == 1);
+ TEST_ASSERT(!strcmp(s.buf, "123"));
+ TEST_ASSERT(s.guard[0] == 0x5a);
+}
(mynewt-core) 01/07: libc/baselibc: Fix size overflow check in malloc and realloc
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 914abe1e2ffca892977f0b0b8983b5a710a6adbe
Author: Szymon Janc <sz...@codecoup.pl>
AuthorDate: Sun Oct 25 23:23:27 2026 +0100
libc/baselibc: Fix size overflow check in malloc and realloc
Requested size is increased by arena header size and rounded up, but
the check allowed sizes for which this wrapped around to 0. For sizes
just below SIZE_MAX malloc corrupted heap metadata and returned a
pointer to a zero sized block instead of failing.
Assisted-by: Claude:claude-opus-5-5
---
libc/baselibc/src/malloc.c | 3 ++-
libc/baselibc/src/realloc.c | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/libc/baselibc/src/malloc.c b/libc/baselibc/src/malloc.c
index 2bf45515d..909794898 100644
--- a/libc/baselibc/src/malloc.c
+++ b/libc/baselibc/src/malloc.c
@@ -149,7 +149,8 @@ void *malloc(size_t size)
void *more_mem;
extern void *_sbrk(int incr);
- if (size == 0 || size > (SIZE_MAX - sizeof(struct arena_header))) {
+ /* Make sure that adding arena header and rounding up does not wrap */
+ if (size == 0 || size > (SIZE_MAX - 2 * sizeof(struct arena_header))) {
return NULL;
}
diff --git a/libc/baselibc/src/realloc.c b/libc/baselibc/src/realloc.c
index 5bfab3136..52e983b0c 100644
--- a/libc/baselibc/src/realloc.c
+++ b/libc/baselibc/src/realloc.c
@@ -18,7 +18,7 @@ void *realloc(void *ptr, size_t size)
if (!ptr)
return malloc(size);
- if (size == 0 || size > (SIZE_MAX - sizeof(struct arena_header))) {
+ if (size == 0 || size > (SIZE_MAX - 2 * sizeof(struct arena_header))) {
free(ptr);
return NULL;
}