-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Limit scope of libc usage in note-c. (#126)
- Loading branch information
1 parent
e2b029d
commit 2d3f0b1
Showing
8 changed files
with
291 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#!/bin/bash | ||
|
||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) | ||
ROOT_SRC_DIR="$SCRIPT_DIR/.." | ||
|
||
if [[ ! -f "$ROOT_SRC_DIR/CMakeLists.txt" ]]; then | ||
echo "Failed to find note-c root directory. (did the location of check_libc_dependencies.sh change?)" | ||
exit 1 | ||
fi | ||
|
||
pushd $ROOT_SRC_DIR $@ > /dev/null | ||
|
||
CMAKE_OPTIONS="-DNOTE_C_NO_LIBC=1" | ||
|
||
cmake -B build/ $CMAKE_OPTIONS | ||
if [[ $? -ne 0 ]]; then | ||
echo "Failed to run CMake." | ||
popd $@ > /dev/null | ||
exit 1 | ||
fi | ||
|
||
PERMITTED_FNS=( | ||
# The mem* functions are ok. | ||
"memchr" | ||
"memcmp" | ||
"memcpy" | ||
"memmove" | ||
"memset" | ||
# These string functions are ok. | ||
"strchr" | ||
"strcmp" | ||
"strlen" | ||
"strncmp" | ||
"strstr" | ||
# TODO: The only explicit usage of strtod is in the cJSON code if | ||
# CJSON_NO_CLIB is NOT true. It's true by default, so we need to figure out | ||
# why strtod is still being brought in. | ||
"strtod" | ||
# strtol comes from us using atoi in NoteGetEnvInt. | ||
"strtol" | ||
# Used by NotePrintf. | ||
"vsnprintf" | ||
) | ||
|
||
# Function to check if an element is in an array. | ||
element_in_array() { | ||
local element="$1" | ||
local array=("${@:2}") | ||
|
||
for item in "${array[@]}"; do | ||
if [ "$item" == "$element" ]; then | ||
return 0 # Element found in array | ||
fi | ||
done | ||
return 1 # Element not found in array | ||
} | ||
|
||
BUILD_OUTPUT=$(cmake --build build/ -j 2>&1) | ||
if [[ $? -ne 0 ]]; then | ||
# Iterate over the lines from the build output to get all the undefined | ||
# references. | ||
UNDEF_REFS=() | ||
while IFS= read -r LINE; do | ||
PATTERN="undefined reference to \`(.*)'" | ||
if [[ $LINE =~ $PATTERN ]]; then | ||
UNDEF_REFS+=("${BASH_REMATCH[1]}") | ||
fi | ||
done <<< "$BUILD_OUTPUT" | ||
|
||
# Remove duplicates | ||
UNDEF_REFS=($(printf "%s\n" "${UNDEF_REFS[@]}" | sort -u)) | ||
|
||
# Check if each function that caused an undefined reference error is | ||
# permitted. | ||
FAIL=0 | ||
for UNDEF_REF in "${UNDEF_REFS[@]}"; do | ||
if element_in_array "$UNDEF_REF" "${PERMITTED_FNS[@]}"; then | ||
echo "$UNDEF_REF is permitted." | ||
else | ||
echo "$UNDEF_REF is NOT permitted" | ||
FAIL=1 | ||
fi | ||
done | ||
|
||
if [ "$FAIL" -eq 1 ]; then | ||
echo "Unpermitted libc functions found." | ||
popd $@ > /dev/null | ||
exit 1 | ||
fi | ||
else | ||
echo "Build unexpectedly succeeded. The build should fail because certain permitted libc functions shouldn't be found when linking." | ||
popd $@ > /dev/null | ||
exit 1 | ||
fi | ||
|
||
popd $@ > /dev/null |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/*! | ||
* @file JPrintUnformatted_test.cpp | ||
* | ||
* Written by the Blues Inc. team. | ||
* | ||
* Copyright (c) 2023 Blues Inc. MIT License. Use of this source code is | ||
* governed by licenses granted by the copyright holder including that found in | ||
* the | ||
* <a href="https://github.com/blues/note-c/blob/master/LICENSE">LICENSE</a> | ||
* file. | ||
* | ||
*/ | ||
|
||
#ifdef NOTE_C_TEST | ||
|
||
#include <catch2/catch_test_macros.hpp> | ||
|
||
#include "n_lib.h" | ||
|
||
namespace | ||
{ | ||
|
||
// We typically don't write unit tests for cJSON functions. This is an exception | ||
// because we modified some of the internal cJSON printing code to use strlcpy | ||
// instead of strcpy, and we want to make sure we didn't introduce a bug. | ||
SCENARIO("JPrintUnformatted") | ||
{ | ||
NoteSetFnDefault(malloc, free, NULL, NULL); | ||
|
||
GIVEN("A valid JSON object") { | ||
J *jsonObj = JParse("{" | ||
"\"string\": \"Hello, World!\"," | ||
"\"number\": 42," | ||
"\"boolean\": true," | ||
"\"nullValue\": null," | ||
"\"array\": [1, \"two\", false, 3.14]," | ||
"\"nestedObject\": {" | ||
"\"key1\": \"value1\"," | ||
"\"key2\": 123," | ||
"\"key3\": {" | ||
"\"subKey1\": true," | ||
"\"subKey2\": [\"apple\", \"banana\", \"cherry\"]" | ||
"}" | ||
"}" | ||
"}"); | ||
|
||
REQUIRE(jsonObj != NULL); | ||
|
||
WHEN("JPrintUnformatted is called on that object") { | ||
char *result = JPrintUnformatted(jsonObj); | ||
|
||
THEN("A non-NULL, non-zero length string is returned") { | ||
REQUIRE(result != NULL); | ||
CHECK(strlen(result) > 0); | ||
} | ||
|
||
JFree(result); | ||
} | ||
|
||
JDelete(jsonObj); | ||
} | ||
} | ||
|
||
} | ||
|
||
#endif // NOTE_C_TEST |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/*! | ||
* @file Jtolower_test.cpp | ||
* | ||
* Written by the Blues Inc. team. | ||
* | ||
* Copyright (c) 2023 Blues Inc. MIT License. Use of this source code is | ||
* governed by licenses granted by the copyright holder including that found in | ||
* the | ||
* <a href="https://github.com/blues/note-c/blob/master/LICENSE">LICENSE</a> | ||
* file. | ||
* | ||
*/ | ||
|
||
#ifdef NOTE_C_TEST | ||
|
||
#include <catch2/catch_test_macros.hpp> | ||
|
||
#include "n_lib.h" | ||
#include "test_static.h" | ||
|
||
namespace | ||
{ | ||
|
||
SCENARIO("Jtolower") | ||
{ | ||
const char alphabetUpper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
const char alphabetLower[] = "abcdefghijklmnopqrstuvwxyz"; | ||
char result[sizeof(alphabetUpper)] = {0}; | ||
|
||
GIVEN("The uppercase characters of the alphabet") { | ||
WHEN("Jtolower is called on each letter") { | ||
for (size_t i = 0; i < sizeof(alphabetUpper); ++i) { | ||
result[i] = Jtolower(alphabetUpper[i]); | ||
} | ||
|
||
THEN("The corresponding lowercase letter is returned") { | ||
for (size_t i = 0; i < sizeof(alphabetUpper); ++i) { | ||
CHECK(result[i] == alphabetLower[i]); | ||
} | ||
} | ||
} | ||
} | ||
|
||
GIVEN("The lowercase characters of the alphabet") { | ||
WHEN("Jtolower is called on each letter") { | ||
for (size_t i = 0; i < sizeof(alphabetLower); ++i) { | ||
result[i] = Jtolower(alphabetLower[i]); | ||
} | ||
|
||
THEN("The same lowercase letter is returned") { | ||
for (size_t i = 0; i < sizeof(alphabetLower); ++i) { | ||
CHECK(result[i] == alphabetLower[i]); | ||
} | ||
} | ||
} | ||
} | ||
|
||
GIVEN("A non-letter char") { | ||
char invalid = '.'; | ||
|
||
WHEN("Jtolower is called on that char") { | ||
char invalidResult = Jtolower(invalid); | ||
|
||
THEN("The non-letter char is returned") { | ||
CHECK(invalidResult == invalid); | ||
} | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
#endif // NOTE_C_TEST |