Repository navigation
sftp: bound reply lengths before client allocs #3097
Workflow file for this run
This file contains hidden or 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
| name: Windows Build Test | |
| on: | |
| push: | |
| branches: [ 'master', 'main', 'release/**' ] | |
| pull_request: | |
| branches: [ '*' ] | |
| workflow_dispatch: | |
| env: | |
| WOLFSSL_SOLUTION_FILE_PATH: wolfssl64.sln | |
| SOLUTION_FILE_PATH: wolfssh.sln | |
| USER_SETTINGS_H_NEW: wolfssh/ide/winvs/user_settings.h | |
| USER_SETTINGS_H: wolfssl/IDE/WIN/user_settings.h | |
| INCLUDE_DIR: wolfssh | |
| # Configuration type to build. | |
| # You can convert this to a build matrix if you need coverage of multiple configuration types. | |
| # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix | |
| WOLFSSL_BUILD_CONFIGURATION: Release | |
| WOLFSSH_BUILD_CONFIGURATION: Release | |
| BUILD_PLATFORM: x64 | |
| TARGET_PLATFORM: 10 | |
| jobs: | |
| build: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v2 | |
| with: | |
| repository: wolfssl/wolfssl | |
| path: wolfssl | |
| - uses: actions/checkout@master | |
| with: | |
| path: wolfssh | |
| - name: Add MSBuild to PATH | |
| uses: microsoft/setup-msbuild@v1 | |
| - name: Restore wolfSSL NuGet packages | |
| working-directory: ${{env.GITHUB_WORKSPACE}}wolfssl | |
| run: nuget restore ${{env.WOLFSSL_SOLUTION_FILE_PATH}} | |
| - name: Enable wolfSSH options (sshd, sftp, x509) in user_settings.h | |
| working-directory: ${{env.GITHUB_WORKSPACE}} | |
| shell: bash | |
| run: | | |
| sed -i 's/#if 0/#if 1/g' ${{env.USER_SETTINGS_H_NEW}} | |
| cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}} | |
| - name: Build wolfssl library | |
| working-directory: ${{env.GITHUB_WORKSPACE}}wolfssl | |
| run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:Configuration=${{env.WOLFSSL_BUILD_CONFIGURATION}} /t:wolfssl ${{env.WOLFSSL_SOLUTION_FILE_PATH}} | |
| - name: Restore NuGet packages | |
| working-directory: ${{env.GITHUB_WORKSPACE}}wolfssh\ide\winvs | |
| run: nuget restore ${{env.SOLUTION_FILE_PATH}} | |
| - name: Build wolfssh | |
| working-directory: ${{env.GITHUB_WORKSPACE}}wolfssh\ide\winvs | |
| # Add additional options to the MSBuild command line here (like platform or verbosity level). | |
| # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference | |
| run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:WindowsTargetPlatformVersion=${{env.TARGET_PLATFORM}} /p:Configuration=${{env.WOLFSSH_BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} | |
| - name: Locate wolfsshd.exe and stage wolfssl.dll | |
| working-directory: ${{ github.workspace }}\wolfssh | |
| shell: pwsh | |
| run: | | |
| $sshdExe = Get-ChildItem -Path "${{ github.workspace }}\wolfssh" -Recurse -Filter "wolfsshd.exe" -ErrorAction SilentlyContinue | | |
| Where-Object { $_.FullName -like "*Release*" } | Select-Object -First 1 | |
| if (-not $sshdExe) { | |
| Write-Host "ERROR: wolfsshd.exe not found" | |
| exit 1 | |
| } | |
| Add-Content -Path $env:GITHUB_ENV -Value "SSHD_PATH=$($sshdExe.FullName)" | |
| $sshdDir = Split-Path -Parent $sshdExe.FullName | |
| $wolfsslDll = Get-ChildItem -Path "${{ github.workspace }}\wolfssl" -Recurse -Filter "wolfssl.dll" -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| if ($wolfsslDll -and -not (Test-Path (Join-Path $sshdDir "wolfssl.dll"))) { | |
| Copy-Item -Path $wolfsslDll.FullName -Destination (Join-Path $sshdDir "wolfssl.dll") -Force | |
| } | |
| - name: Test LoginGraceTime enforcement on Windows | |
| working-directory: ${{ github.workspace }}\wolfssh\apps\wolfsshd\test | |
| shell: pwsh | |
| timeout-minutes: 2 | |
| run: .\sshd_login_grace_test.ps1 -SshdExe "$env:SSHD_PATH" | |
| - name: Test wolfsshd -D option parsing on Windows | |
| working-directory: ${{ github.workspace }}\wolfssh\apps\wolfsshd\test | |
| shell: pwsh | |
| timeout-minutes: 2 | |
| run: .\sshd_dash_d_test.ps1 -SshdExe "$env:SSHD_PATH" | |
| # Build and run the self-contained unit tests with the MSVC AddressSanitizer. | |
| # This is the only job that executes wolfSSH tests under a sanitizer on | |
| # Windows, where the USE_WINDOWS_API console code (e.g. wolfSSH_DoOSC) is | |
| # compiled, so it guards that path against out-of-bounds reads. | |
| asan-tests: | |
| runs-on: windows-latest | |
| env: | |
| # print_stats=1 emits allocator stats at exit, positive evidence that the | |
| # ASan runtime was active in-process during each test run. | |
| ASAN_OPTIONS: abort_on_error=1:print_stats=1 | |
| steps: | |
| - uses: actions/checkout@v2 | |
| with: | |
| repository: wolfssl/wolfssl | |
| path: wolfssl | |
| - uses: actions/checkout@master | |
| with: | |
| path: wolfssh | |
| - name: Add MSBuild to PATH | |
| uses: microsoft/setup-msbuild@v1 | |
| # The pinned v142 toolset does not ship the AddressSanitizer runtime libs on | |
| # the runner. Find an installed MSVC toolset that does and build everything in | |
| # this job with it, recording its lib/bin dirs for the link and run steps. | |
| # wolfssl, wolfssh and the test projects must share one compiler version | |
| # because /GL (whole program optimization) does code generation at link time. | |
| - name: Locate MSVC AddressSanitizer runtime | |
| shell: pwsh | |
| run: | | |
| $vs = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath | |
| $lib = Get-ChildItem "$vs\VC\Tools\MSVC\*\lib\x64\clang_rt.asan_dynamic_runtime_thunk-x86_64.lib" -ErrorAction SilentlyContinue | | |
| Sort-Object { [version]($_.FullName -replace '.*\\MSVC\\([0-9.]+)\\.*','$1') } | | |
| Select-Object -Last 1 | |
| if ($null -eq $lib) { throw "MSVC AddressSanitizer runtime not found in any installed toolset" } | |
| $msvcDir = $lib.Directory.Parent.Parent.FullName | |
| $ver = [version]($msvcDir.Split('\')[-1]) | |
| if ($ver.Minor -ge 30) { $toolset = "v143" } else { $toolset = "v142" } | |
| "ASAN_TOOLSET=$toolset" | Out-File $env:GITHUB_ENV -Append | |
| "ASAN_LIB_DIR=$($lib.Directory.FullName)" | Out-File $env:GITHUB_ENV -Append | |
| "ASAN_BIN_DIR=$(Join-Path $msvcDir 'bin\Hostx64\x64')" | Out-File $env:GITHUB_ENV -Append | |
| Write-Host "Using toolset $toolset (MSVC $ver)" | |
| - name: Restore wolfSSL NuGet packages | |
| working-directory: wolfssl | |
| run: nuget restore ${{env.WOLFSSL_SOLUTION_FILE_PATH}} | |
| # These env paths already include the wolfssh/ and wolfssl/ checkout | |
| # prefixes, so this runs from the default working directory, the workspace | |
| # root. | |
| - name: Enable wolfSSH options (sshd, sftp, x509) in user_settings.h | |
| shell: bash | |
| run: | | |
| sed -i 's/#if 0/#if 1/g' ${{env.USER_SETTINGS_H_NEW}} | |
| cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}} | |
| # WholeProgramOptimization=false disables /GL so the v142-independent objects | |
| # link without a cross-version code-generation requirement (C1047). | |
| - name: Build wolfssl library | |
| working-directory: wolfssl | |
| shell: pwsh | |
| run: | | |
| msbuild /m /p:PlatformToolset=$env:ASAN_TOOLSET /p:Platform=${{env.BUILD_PLATFORM}} /p:Configuration=${{env.WOLFSSL_BUILD_CONFIGURATION}} /p:WholeProgramOptimization=false /t:wolfssl ${{env.WOLFSSL_SOLUTION_FILE_PATH}} | |
| if ($LASTEXITCODE -ne 0) { throw "wolfssl build failed" } | |
| - name: Restore NuGet packages | |
| working-directory: wolfssh\ide\winvs | |
| run: nuget restore ${{env.SOLUTION_FILE_PATH}} | |
| # EnableASAN=true adds /fsanitize=address to each test project and to the | |
| # referenced wolfssh library project, instrumenting src/wolfterm.c. The | |
| # AddressSanitizer lib dir is added to LIB so the runtime thunk resolves. | |
| - name: Build api-test and unit-test with AddressSanitizer | |
| working-directory: wolfssh\ide\winvs | |
| shell: pwsh | |
| run: | | |
| $env:LIB = "$env:ASAN_LIB_DIR;$env:LIB" | |
| foreach ($p in @("api-test\api-test.vcxproj", "unit-test\unit-test.vcxproj")) { | |
| msbuild /m /p:PlatformToolset=$env:ASAN_TOOLSET /p:Platform=${{env.BUILD_PLATFORM}} /p:WindowsTargetPlatformVersion=${{env.TARGET_PLATFORM}} /p:Configuration=${{env.WOLFSSH_BUILD_CONFIGURATION}} /p:EnableASAN=true /p:WholeProgramOptimization=false $p | |
| if ($LASTEXITCODE -ne 0) { throw "build failed: $p" } | |
| } | |
| # Positive control: compile a deliberate heap overflow with the same toolset | |
| # and confirm ASan aborts on it. This proves ASan detection actually works on | |
| # this runner, so a clean test run is meaningful rather than a silent no-op. | |
| - name: Verify AddressSanitizer detection (positive control) | |
| shell: pwsh | |
| run: | | |
| $vs = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath | |
| Import-Module "$vs\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" | |
| Enter-VsDevShell -VsInstallPath $vs -SkipAutomaticLocation -DevCmdArguments "-arch=x64" | Out-Null | |
| Set-Content canary.c 'int main(int argc, char** argv) { volatile char b[1]; (void)argv; return b[argc + 10]; }' | |
| cl /nologo /fsanitize=address /MD canary.c | |
| if ($LASTEXITCODE -ne 0) { throw "canary failed to compile" } | |
| $out = & .\canary.exe 2>&1 | Out-String | |
| $code = $LASTEXITCODE | |
| Write-Host $out | |
| if ($code -eq 0 -or $out -notmatch "AddressSanitizer") { | |
| throw "Positive control FAILED: ASan did not detect the deliberate overflow" | |
| } | |
| Write-Host "Positive control OK: ASan detected the deliberate out-of-bounds access" | |
| # canary.exe aborts with a non-zero code by design; reset so the step | |
| # itself reports success. | |
| exit 0 | |
| # Building a .vcxproj directly leaves $(SolutionDir) unset, so each project | |
| # writes to its own <project>\Release\x64 dir. Run from the wolfssh repo root | |
| # so the tests find keys/ and certs/, and copy the dynamic ASAN runtime next | |
| # to each binary so it loads without a full developer-prompt environment. | |
| - name: Run tests under AddressSanitizer | |
| working-directory: wolfssh | |
| shell: pwsh | |
| run: | | |
| $cfg = "${{env.WOLFSSH_BUILD_CONFIGURATION}}\${{env.BUILD_PLATFORM}}" | |
| $dll = Join-Path $env:ASAN_BIN_DIR "clang_rt.asan_dynamic-x86_64.dll" | |
| if (-not (Test-Path $dll)) { throw "ASAN runtime DLL not found: $dll" } | |
| foreach ($t in @("api-test", "unit-test")) { | |
| $dir = "ide\winvs\$t\$cfg" | |
| # Static signal: confirm the binary really imports the ASan runtime, so | |
| # we are exercising an instrumented build and not a stale one. | |
| $deps = & "$env:ASAN_BIN_DIR\dumpbin.exe" /dependents "$dir\$t.exe" | Out-String | |
| if ($deps -notmatch "clang_rt.asan") { throw "$t is not linked against the ASan runtime" } | |
| Write-Host "$t links the ASan runtime:" | |
| ($deps -split "`n" | Select-String "asan").Line.Trim() | ForEach-Object { Write-Host " $_" } | |
| Copy-Item $dll $dir | |
| & "$dir\$t.exe" | |
| if ($LASTEXITCODE -ne 0) { throw "$t failed under ASAN (exit $LASTEXITCODE)" } | |
| } | |
| # Build and run the autotools regression tests under MSYS2 MinGW64. MinGW | |
| # defines _WIN32, so wolfssh/settings.h turns on USE_WINDOWS_API and the | |
| # Windows-only coverage in tests/regress.c (TestSftpWindowsOpenFlagMatrix, | |
| # which walks the RecvOpen CREAT/EXCL/TRUNC/APPEND matrix against the | |
| # CreateFile() disposition table) actually compiles and runs. The MSVC | |
| # solution has no regress project and regress.c does not build with cl (it | |
| # uses arpa/inet.h and unistd.h), so without this job that matrix runs in no | |
| # CI at all. wolfsshd is left out of the build: its autotools path is not | |
| # MinGW-clean and the MSVC solution already covers it. | |
| mingw-regress: | |
| name: MSYS2 MinGW64 regression tests | |
| runs-on: windows-latest | |
| timeout-minutes: 40 | |
| # Pinned rather than left on wolfssl/wolfssl's default branch, so an | |
| # upstream wolfSSL change can't silently break this job. Matches the | |
| # ref singlethread-check.yml and x509-interop.yml already pin to. | |
| env: | |
| WOLFSSL_REF: v5.9.1-stable | |
| defaults: | |
| run: | |
| shell: msys2 {0} | |
| steps: | |
| - name: Set up MSYS2 MinGW64 | |
| uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: MINGW64 | |
| update: false | |
| install: >- | |
| base-devel | |
| autotools | |
| git | |
| mingw-w64-x86_64-gcc | |
| mingw-w64-x86_64-pkgconf | |
| # The msys2 shell's $HOME isn't a stable path across runner images (it | |
| # lives under setup-msys2's temp install dir), so build to a | |
| # workspace-relative path instead: actions/cache resolves a relative | |
| # `path:` against GITHUB_WORKSPACE, and that same directory is what the | |
| # rest of this job's msys2 steps read back through $WOLFSSL_INSTALL. | |
| - name: Resolve wolfssl install prefix | |
| run: echo "WOLFSSL_INSTALL=$(cygpath -u "$GITHUB_WORKSPACE")/wolfssl-install" >> "$GITHUB_ENV" | |
| # A single job, unlike the build_wolfssl/build_wolfssh split | |
| # singlethread-check.yml and x509-interop.yml use: no lookup-only here, | |
| # since there is no downstream job for a second cache step to restore | |
| # into. This one restores on a hit and saves automatically post-job on | |
| # a miss. | |
| - name: Cache wolfssl build | |
| uses: actions/cache@v5 | |
| id: cache-wolfssl | |
| with: | |
| path: wolfssl-install | |
| key: wolfssh-mingw-regress-wolfssl-${{ env.WOLFSSL_REF }}-windows-latest | |
| - name: Checkout wolfssl | |
| if: steps.cache-wolfssl.outputs.cache-hit != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: wolfssl/wolfssl | |
| ref: ${{ env.WOLFSSL_REF }} | |
| path: wolfssl | |
| - name: Build and install wolfssl | |
| if: steps.cache-wolfssl.outputs.cache-hit != 'true' | |
| working-directory: wolfssl | |
| run: | | |
| ./autogen.sh | |
| # --enable-all pulls in --enable-crl-monitor, which wolfSSL's configure | |
| # rejects on MinGW (it is limited to linux, OS X, and freebsd). Turn it | |
| # back off explicitly; wolfSSH does not use the CRL monitor. | |
| ./configure --enable-all --disable-crl-monitor \ | |
| --enable-static --disable-shared \ | |
| --prefix="$WOLFSSL_INSTALL" | |
| make -j$(nproc) | |
| make install | |
| - name: Checkout wolfssh | |
| uses: actions/checkout@v4 | |
| with: | |
| path: wolfssh | |
| - name: Build and run the regression tests | |
| working-directory: wolfssh | |
| run: | | |
| # Run autoreconf directly instead of ./autogen.sh: for a git checkout | |
| # autogen.sh exports WARNINGS="all,error", turning autotools warnings | |
| # into errors that the MSYS2 automake can trip on. | |
| autoreconf -ivf | |
| # wolfssl is a static archive here, so its Windows socket (ws2_32) and | |
| # certificate store (crypt32) references are only resolved when this | |
| # configure's own AC_CHECK_LIB and later link steps pull them in too. | |
| ./configure --enable-sftp \ | |
| CPPFLAGS="-I$WOLFSSL_INSTALL/include" \ | |
| LDFLAGS="-L$WOLFSSL_INSTALL/lib" \ | |
| LIBS="-lws2_32 -lcrypt32" | |
| # MinGW's EXEEXT is ".exe", so the check_PROGRAMS targets automake | |
| # generates are tests/regress.test.exe and tests/unit.test.exe, not | |
| # the extension-less names make would use on a POSIX host. | |
| make -j$(nproc) tests/regress.test.exe tests/unit.test.exe | |
| ./tests/regress.test.exe | |
| ./tests/unit.test.exe | |
| - name: Show config.log on failure | |
| if: failure() | |
| working-directory: wolfssh | |
| run: cat config.log |