diff --git a/.github/workflows/sanitizers.yaml b/.github/workflows/sanitizers.yaml new file mode 100644 index 0000000..b99fb6d --- /dev/null +++ b/.github/workflows/sanitizers.yaml @@ -0,0 +1,110 @@ +--- +name: Sanitizers +on: + pull_request: + branches: + - main + paths-ignore: + - 'docs/**' + push: + branches: + - main + paths-ignore: + - 'docs/**' +permissions: + contents: read +jobs: + # Adapted from https://github.com/beberlei/hdrhistogram-php + sanitizers: + name: ${{ matrix.sanitizer }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sanitizer: ['asan', 'msan'] + env: + CFLAGS: -g -O0 -fsanitize=${{ matrix.sanitizer == 'asan' && 'address' || 'memory' }} -DZEND_TRACK_ARENA_ALLOC + LDFLAGS: -fsanitize=${{ matrix.sanitizer == 'asan' && 'address' || 'memory' }} + CC: clang + CXX: clang++ + USE_ZEND_ALLOC: 0 + LIBRARY_PATH: ${{ github.workspace }}/php/target/lib + LD_LIBRARY_PATH: ${{ github.workspace }}/php/target/lib + steps: + - + name: Remove local PHP + run: sudo apt-get remove --purge --autoremove 'php*' 'libmemcached*' + - + uses: actions/checkout@v4 + - + uses: actions/setup-go@v5 + with: + go-version: '1.22' + cache-dependency-path: | + go.sum + caddy/go.sum + - + name: Determine PHP version + id: determine-php-version + run: | + curl -fsSL 'https://www.php.net/releases/index.php?json&max=1&version=8.3' -o version.json + echo version="$(jq -r 'keys[0]' version.json)" >> "$GITHUB_OUTPUT" + echo archive="$(jq -r '.[] .source[] | select(.filename |endswith(".xz")) | "https://www.php.net/distributions/" + .filename' version.json)" >> "$GITHUB_OUTPUT" + - + name: Cache PHP + id: cache-php + uses: actions/cache@v4 + with: + path: php/target + key: php-sanitizers-${{ matrix.sanitizer }}-${{ runner.arch }}-${{ steps.determine-php-version.outputs.version }} + - + if: steps.cache-php.outputs.cache-hit != 'true' + name: Compile PHP + run: | + mkdir php/ + curl -fsSL "${{ steps.determine-php-version.outputs.archive }}" | tar -Jx -C php --strip-components=1 + cd php/ + ./configure \ + CFLAGS="$CFLAGS" \ + LDFLAGS="$LDFLAGS" \ + --enable-debug \ + --enable-embed \ + --enable-zts \ + --enable-option-checking=fatal \ + --disable-zend-signals \ + --without-sqlite3 \ + --without-pdo-sqlite \ + --without-libxml \ + --disable-dom \ + --disable-simplexml \ + --disable-xml \ + --disable-xmlreader \ + --disable-xmlwriter \ + --without-pcre-jit \ + --disable-opcache-jit \ + --disable-cli \ + --disable-cgi \ + --disable-phpdbg \ + --without-pear \ + --disable-mbregex \ + --enable-werror \ + ${{ matrix.sanitizer == 'msan' && '--enable-memory-sanitizer' || '' }} \ + --prefix="$(pwd)/target/" + make -j"$(getconf _NPROCESSORS_ONLN)" + sudo make install + - + name: Add PHP to the PATH + run: echo "$(pwd)/php/target/bin" >> "$GITHUB_PATH" + - + name: Set Set CGO flags + run: | + { + echo "CGO_CFLAGS=$CFLAGS $(php-config --includes)" + echo "CGO_LDFLAGS=$LDFLAGS $(php-config --ldflags) $(php-config --libs)" + } >> "$GITHUB_ENV" + - + name: Compile tests + run: go test -${{ matrix.sanitizer }} -v -x -c + - + name: Run tests + run: ./frankenphp.test -test.v diff --git a/Dockerfile b/Dockerfile index 774ab86..2e70cb9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -86,9 +86,10 @@ COPY --link caddy caddy COPY --link internal internal COPY --link testdata testdata -# todo: automate this? -# see https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 for PHP values -ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS" CGO_CPPFLAGS=$PHP_CPPFLAGS +# See https://github.com/docker-library/php/blob/master/8.3/bookworm/zts/Dockerfile#L57-L59 for PHP values +ENV CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS" +ENV CGO_CPPFLAGS=$PHP_CPPFLAGS +ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" WORKDIR /go/src/app/caddy/frankenphp RUN GOBIN=/usr/local/bin go install -ldflags "-w -s -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \ diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 9918657..d9d4f02 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -104,9 +104,10 @@ COPY --link caddy caddy COPY --link internal internal COPY --link testdata testdata -# todo: automate this? -# see https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 for php values -ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS" CGO_CPPFLAGS=$PHP_CPPFLAGS +# See https://github.com/docker-library/php/blob/master/8.3/alpine3.20/zts/Dockerfile#L53-L55 +ENV CGO_CFLAGS="-DFRANKENPHP_VERSION=$FRANKENPHP_VERSION $PHP_CFLAGS" +ENV CGO_CPPFLAGS=$PHP_CPPFLAGS +ENV CGO_LDFLAGS="-lssl -lcrypto -lreadline -largon2 -lcurl -lonig -lz $PHP_LDFLAGS" WORKDIR /go/src/app/caddy/frankenphp RUN GOBIN=/usr/local/bin go install -ldflags "-w -s -extldflags '-Wl,-z,stack-size=0x80000' -X 'github.com/caddyserver/caddy/v2.CustomVersion=FrankenPHP $FRANKENPHP_VERSION PHP $PHP_VERSION Caddy'" && \ diff --git a/build-static.sh b/build-static.sh index 25c327e..a27de95 100755 --- a/build-static.sh +++ b/build-static.sh @@ -120,14 +120,20 @@ else ./bin/spc build --debug --enable-zts --build-embed ${extraOpts} "${PHP_EXTENSIONS}" --with-libs="${PHP_EXTENSION_LIBS}" fi +# See https://github.com/docker-library/php/blob/master/8.3/alpine3.20/zts/Dockerfile#L53-L55 CGO_CFLAGS="-DFRANKENPHP_VERSION=${FRANKENPHP_VERSION} -I${PWD}/buildroot/include/ $(./buildroot/bin/php-config --includes | sed s#-I/#-I"${PWD}"/buildroot/#g)" if [ -n "${DEBUG_SYMBOLS}" ]; then CGO_CFLAGS="-g ${CGO_CFLAGS}" +else + CGO_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ${CGO_CFLAGS}" fi export CGO_CFLAGS +export CGO_CPPFLAGS="${CGO_CFLAGS}" if [ "${os}" = "mac" ]; then export CGO_LDFLAGS="-framework CoreFoundation -framework SystemConfiguration" +elif [ "${os}" = "linux" ] && [ -z "${DEBUG_SYMBOLS}" ]; then + CGO_LDFLAGS="-Wl,-O1 -pie" fi CGO_LDFLAGS="${CGO_LDFLAGS} ${PWD}/buildroot/lib/libbrotlicommon.a ${PWD}/buildroot/lib/libbrotlienc.a ${PWD}/buildroot/lib/libbrotlidec.a $(./buildroot/bin/php-config --ldflags || true) $(./buildroot/bin/php-config --libs || true)" diff --git a/frankenphp.go b/frankenphp.go index 4bb6a04..3bb21ff 100644 --- a/frankenphp.go +++ b/frankenphp.go @@ -13,13 +13,11 @@ package frankenphp // We also set these flags for hardening: https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 // #cgo darwin pkg-config: libxml-2.0 -// #cgo CFLAGS: -Wall -Werror -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 // #cgo CFLAGS: -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib // #cgo linux CFLAGS: -D_GNU_SOURCE -// #cgo CPPFLAGS: -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 // #cgo darwin LDFLAGS: -L/opt/homebrew/opt/libiconv/lib -liconv -// #cgo linux LDFLAGS: -Wl,-O1 -lresolv -// #cgo LDFLAGS: -pie -L/usr/local/lib -L/usr/lib -lphp -ldl -lm -lutil +// #cgo linux LDFLAGS: -lresolv +// #cgo LDFLAGS: -L/usr/local/lib -L/usr/lib -lphp -ldl -lm -lutil // #include // #include // #include