Skip to content

Commit

Permalink
adding the files for the action
Browse files Browse the repository at this point in the history
  • Loading branch information
Ximaz committed May 4, 2024
0 parents commit 738270c
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
INPUT_BINARY_ARGS=""
INPUT_BINARY_PATH=""
INPUT_LD_LIBRARY_PATH=""
INPUT_TRACK_FILE_DESCRIPTORS=""
INPUT_TREAT_ERROR_AS_WARNING="false"
INPUT_VALGRIND_SUPPRESSIONS=""
INPUT_VERBOSE="false"
HOME="/root"
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.env
valgrind-reports.log
test
tests
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM debian:stable

RUN apt update -y \
&& apt upgrade -y \
&& apt install -y build-essential valgrind

WORKDIR /root/

COPY valgrind.sh /root/valgrind.sh

ENTRYPOINT ["./valgrind.sh"]
34 changes: 34 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: "Valgrind"
description: "Check for memory leaks, poorly managed or even not managed memory, and unclosed file descriptors."
branding:
icon: "archive"
color: "blue"
inputs:
binary_args:
description: "The args to pass to the binary once started (string format)"
required: false
binary_path:
description: "The binary to run Valgrind over"
required: true
ld_library_path:
description: "Custom library path (for dymanic locally-compiled libraries)"
required: false
track_file_descriptors:
description: "Whether or not to track file descriptors (true or false)"
required: false
default: true
treat_error_as_warning:
description: "The workflow won't exit as error, and error annotations will be replaced by warnings"
required: false
default: false
valgrind_suppressions:
description: "String containing Valgrind suppressions (will be put inside a suppressions file)"
required: false
verbose:
description: "Asking Valgrind to be verbose"
required: false
default: false

runs:
using: "docker"
image: "Dockerfile"
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: "3.9"

services:
valgrind-action:
build:
dockerfile: Dockerfile
context: .
image: valgrind-action
container_name: valgrind-tester
env_file:
- .env
volumes:
- ./:/root/
103 changes: 103 additions & 0 deletions valgrind.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
# set -xeu

prepare_valgrind_flags() {
local SUPPRESSIONS_FILE="valgrind.supp"

echo "--show-error-list=yes"
echo "--leak-check=full"
echo "--track-origins=yes"
echo "--read-var-info=yes"
echo "--trace-children=yes"
echo "--show-leak-kinds=all"
echo "--read-inline-info=yes"
echo "--errors-for-leak-kinds=all"
echo "--expensive-definedness-checks=yes"
echo "--gen-suppressions=all"
[[ "${INPUT_TRACK_FILE_DESCRIPTORS}" == "true" ]] && echo "--track-fds=yes"
[[ "${INPUT_VERBOSE}" == "true" ]] && echo "--verbose"
if [[ "${INPUT_VALGRIND_SUPPRESSIONS}" != "" ]]; then
echo "${INPUT_VALGRIND_SUPPRESSIONS}" > "${SUPPRESSIONS_FILE}"
echo "--suppressions=${SUPPRESSIONS_FILE}"
fi
}

match_pattern() {
if [[ $(echo "${1}" | grep "${2}") != "" ]]; then
echo "1"
else
echo "0"
fi
}

skip_criterion_pipe_leaks() {
# Reason of this skip: https://github.com/Snaipe/Criterion/issues/533
if [[ $(echo "${1}" | grep '^==.*== by 0x.*: stdpipe_options (in /usr/local/lib/libcriterion.so.3.2.0)') == "" &&
$(echo "${1}" | grep '^==.*== Open file descriptor .*: /dev/shm/bxf_arena_.* (deleted)') == "" ]]; then
echo "1"
else
echo "0"
fi
}

parse_valgrind_reports() {
local VALGRIND_REPORTS="${1}"
local status=0
local error=""
local kind="error"

if [[ "${INPUT_TREAT_ERROR_AS_WARNING}" == "true" ]]; then
kind="warning"
fi
while IFS= read -r line; do
if [[ "${error}" != "" ]]; then
if [[ $(echo "${line}" | grep '^==.*== $') && $(skip_criterion_pipe_leaks "${error}") == "1" ]]; then
echo "::${kind} title=Valgrind Report::${error}" >> annotations
error=""
status=1
else
error="${error}%0A${line}"
fi
fi
if [[ $(echo "${line}" | grep '^==.*== .* bytes in .* blocks are definitely lost in loss record .* of .*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== .* bytes in .* blocks are still reachable in loss record .* of .*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Invalid .* of size .*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Open file descriptor .*: .*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Invalid free().*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Mismatched free() / delete / delete \[\].*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Syscall param .* points to uninitialised byte(s).*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Source and destination overlap in .*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Argument .* of function .* has a fishy (possibly negative) value: .*$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== .*alloc() with size 0$') ]]; then
error="${line}"
elif [[ $(echo "${line}" | grep '^==.*== Invalid alignment value: .* (should be power of 2)$') ]]; then
error="${line}"
fi
done < "${VALGRIND_REPORTS}"
if [[ "${kind}" == "warning" ]]; then
exit 0
fi
exit "${status}"
}

main() {
local VALGRIND_REPORTS="valgrind-reports.log"
local VALGRIND_FLAGS=$(prepare_valgrind_flags)

if [[ "${INPUT_LD_LIBRARY_PATH}" == "" ]]; then
export LD_LIBRARY_PATH="${INPUT_LD_LIBRARY_PATH}"
fi
valgrind $VALGRIND_FLAGS "${INPUT_BINARY_PATH}" $INPUT_BINARY_ARGS 2>"${VALGRIND_REPORTS}"
parse_valgrind_reports "${VALGRIND_REPORTS}"
}

main

0 comments on commit 738270c

Please sign in to comment.