-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a CI build that checks for unpermitted libc functions.
After some discussion with Ray, we settled on certain libc functions that we're ok using in note-c. Everything else from libc should be excluded. This commit adds a CMake option to build the note-c library without libc. It also tells the linker to generate errors for undefined references. The result is that we can run this build to see what libc functions we're using in note-c. A new Bash script, check_libc_dependencies.sh, processes the output of this build. If any non-permitted functions are found in the undefined reference errors, the script fails. This protects us against the introduction of non-permitted libc functions. A new job in ci.yml runs this script on every PR and push to master.
- Loading branch information
1 parent
deed538
commit 42f86cb
Showing
3 changed files
with
126 additions
and
0 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
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 |