Unverified Commit 68e55c3a by Patrick Steinhardt Committed by GitHub

Merge pull request #4866 from pks-t/pks/v0.27.6-security

Release v0.27.6
parents 8e0b1729 b6998178
# Travis-CI Build for libgit2
# see travis-ci.org for details
language: c
os:
- linux
- osx
compiler:
- gcc
- clang
# Settings to try
env:
global:
- secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs="
- GITTEST_INVASIVE_FS_SIZE=1
matrix:
- OPTIONS="-DTHREADSAFE=ON -DENABLE_TRACE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_WERROR=ON"
- OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DENABLE_WERROR=ON"
dist: trusty
osx_image: xcode8.3
sudo: false
addons:
apt:
sources:
- sourceline: 'deb https://dl.bintray.com/libgit2/ci-dependencies trusty libgit2deps'
key_url: 'https://bintray.com/user/downloadSubjectPublicKey?username=bintray'
packages:
cmake
curl
libcurl3
libcurl3-gnutls
libcurl4-gnutls-dev
libssh2-1-dev
openssh-client
openssh-server
valgrind
matrix:
fast_finish: true
exclude:
- os: osx
compiler: gcc
include:
- compiler: gcc
env: COVERITY=1
os: linux
dist: trusty
- compiler: gcc
env:
- VALGRIND=1
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
os: linux
dist: trusty
allow_failures:
- env: COVERITY=1
install:
- if [ -f ./script/install-deps-${TRAVIS_OS_NAME}.sh ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi
# Run the Build script and tests
script:
- script/cibuild.sh
# Run Tests
after_success:
- if [ "$TRAVIS_OS_NAME" = "linux" -a -n "$VALGRIND" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi
# Only watch the development and master branches
branches:
only:
- master
- /^maint.*/
# Notify development list when needed
notifications:
irc:
channels:
- irc.freenode.net#libgit2
on_success: change
on_failure: always
use_notice: true
skip_join: true
campfire:
on_success: always
on_failure: always
rooms:
- secure: "sH0dpPWMirbEe7AvLddZ2yOp8rzHalGmv0bYL/LIhVw3JDI589HCYckeLMSB\n3e/FeXw4bn0EqXWEXijVa4ijbilVY6d8oprdqMdWHEodng4KvY5vID3iZSGT\nxylhahO1XHmRynKQLOAvxlc93IlpVW38vQfby8giIY1nkpspb2w="
v0.27.6
-------
This as a security release fixing the following list of issues:
- The function family `git__strtol` is used to parse integers
from a buffer. As the functions do not take a buffer length as
argument, they will scan either until the end of the current
number or until a NUL byte is encountered. Many callers have
been misusing the function and called it on potentially
non-NUL-terminated buffers, resulting in possible out-of-bounds
reads. Callers have been fixed to use `git__strntol` functions
instead and `git__strtol` functions were removed.
- The function `git__strntol64` relied on the undefined behavior
of signed integer overflows. While the code tried to detect
such overflows after they have happened, this is unspecified
behavior and may lead to weird behavior on uncommon platforms.
- In the case where `git__strntol32` was unable to parse an
integer because it doesn't fit into an `int32_t`, it printed an
error message containing the string that is currently being
parsed. The code didn't truncate the string though, which
caused it to print the complete string until a NUL byte is
encountered and not only the currently parsed number. In case
where the string was not NUL terminated, this could have lead
to an out-of-bounds read.
- When parsing tags, all unknown fields that appear before the
tag message are skipped. This skipping is done by using a plain
`strstr(buffer, "\n\n")` to search for the two newlines that
separate tag fields from tag message. As it is not possible to
supply a buffer length to `strstr`, this call may skip over the
buffer's end and thus result in an out of bounds read. As
`strstr` may return a pointer that is out of bounds, the
following computation of `buffer_end - buffer` will overflow
and result in an allocation of an invalid length. Note that
when reading objects from the object database, we make sure to
always NUL terminate them, making the use of `strstr` safe.
- When parsing the "encoding" field of a commit, we may perform
an out of bounds read due to using `git__prefixcmp` instead of
`git__prefixncmp`. This can result in the parsed commit object
containing uninitialized data in both its message encoding and
message fields. Note that when reading objects from the object
database, we make sure to always NUL terminate them, making the
use of `strstr` safe.
v0.27.5
-------
......
libgit2 - the Git linkable library
==================================
[![Travis Build Status](https://secure.travis-ci.org/libgit2/libgit2.svg?branch=master)](http://travis-ci.org/libgit2/libgit2)
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/xvof5b4t5480a2q3/branch/master?svg=true)](https://ci.appveyor.com/project/libgit2/libgit2/branch/master)
[![Azure Pipelines Build Status](https://dev.azure.com/libgit2/libgit2/_apis/build/status/libgit2)](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/639/badge.svg)](https://scan.coverity.com/projects/639)
`libgit2` is a portable, pure C implementation of the Git core methods
......@@ -18,7 +17,7 @@ in your favorite language.
[GitKraken](https://gitkraken.com/) and [gmaster](https://gmaster.io/)
and on Git hosting providers like [GitHub](https://github.com/),
[GitLab](https://gitlab.com/) and
[Visual Studio Team Services](https://visualstudio.com/team-services/).
[Azure DevOps](https://azure.com/devops).
We perform the merge every time you click "merge pull request".
`libgit2` is licensed under a **very permissive license** (GPLv2 with a special
......@@ -87,7 +86,7 @@ What It Can Do
libgit2 provides you with the ability to manage Git repositories in the
programming language of your choice. It's used in production to power many
applications including GitHub.com, Plastic SCM and Visual Studio Team Services.
applications including GitHub.com, Plastic SCM and Azure DevOps.
It does not aim to replace the git tool or its user-facing commands. Some APIs
resemble the plumbing commands as those align closely with the concepts of the
......
version: '{build}'
branches:
only:
- master
- appveyor
- /^maint.*/
environment:
GITTEST_INVASIVE_FS_STRUCTURE: 1
GITTEST_INVASIVE_FS_SIZE: 1
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
GENERATOR: "Visual Studio 10 2010"
ARCH: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
GENERATOR: "Visual Studio 10 2010 Win64"
ARCH: 64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "Visual Studio 14 2015"
ARCH: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "Visual Studio 14 2015 Win64"
ARCH: 64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "MSYS Makefiles"
ARCH: i686 # this is for 32-bit MinGW-w64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GENERATOR: "MSYS Makefiles"
ARCH: 64
cache:
- i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
- x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z
build_script:
- ps: |
mkdir build
cd build
if ($env:GENERATOR -ne "MSYS Makefiles") {
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D BUILD_EXAMPLES=ON -D MSVC_CRTDBG=ON .. -G"$env:GENERATOR"
cmake --build . --config Debug
}
- cmd: |
if "%GENERATOR%"=="MSYS Makefiles" (C:\MinGW\msys\1.0\bin\sh --login /c/projects/libgit2/script/appveyor-mingw.sh)
test_script:
- ps: |
# Disable DHE key exchange to fix intermittent build failures ("A buffer
# provided was too small") due to SChannel bug. See e.g.
# - https://github.com/aws/aws-sdk-cpp/issues/671
# - https://github.com/dotnet/corefx/issues/7812
New-Item HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman -Force | New-ItemProperty -Name Enabled -Value 0 -Force
$ErrorActionPreference="Stop"
Start-FileDownload https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -FileName poxyproxy.jar
# Run this early so we know it's ready by the time we need it
$proxyJob = Start-Job { java -jar $Env:APPVEYOR_BUILD_FOLDER\build\poxyproxy.jar -d --port 8080 --credentials foo:bar }
ctest -V -R libgit2_clar
Receive-Job -Job $proxyJob
$env:GITTEST_REMOTE_PROXY_URL = "localhost:8080"
$env:GITTEST_REMOTE_PROXY_USER = "foo"
$env:GITTEST_REMOTE_PROXY_PASS = "bar"
ctest -V -R libgit2_clar-proxy_credentials
resources:
- repo: self
trigger:
- master
- maint/*
jobs:
- job: linux_trusty_gcc_openssl
displayName: 'Linux (Trusty; GCC; OpenSSL)'
pool:
vmImage: 'Ubuntu 16.04'
steps:
- template: ci/docker.yml
parameters:
imageName: 'libgit2/trusty-openssl:latest'
environmentVariables: |
CC=gcc
LEAK_CHECK=valgrind
- job: linux_trusty_clang_openssl
displayName: 'Linux (Trusty; Clang; OpenSSL)'
pool:
vmImage: 'Ubuntu 16.04'
steps:
- template: ci/docker.yml
parameters:
imageName: 'libgit2/trusty-openssl:latest'
environmentVariables: |
CC=clang
LEAK_CHECK=valgrind
- job: macos
displayName: 'macOS'
pool:
vmImage: 'macOS 10.13'
steps:
- bash: . '$(Build.SourcesDirectory)/ci/setup-osx.sh'
displayName: Setup
- template: ci/bash.yml
parameters:
environmentVariables:
TMPDIR: $(Agent.TempDirectory)
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
LEAK_CHECK: leaks
- job: windows_vs_amd64
displayName: 'Windows (Visual Studio; amd64)'
pool: Hosted
steps:
- template: ci/powershell.yml
parameters:
environmentVariables:
CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 12 2013 Win64"
- job: windows_vs_x86
displayName: 'Windows (Visual Studio; x86)'
pool: Hosted
steps:
- template: ci/powershell.yml
parameters:
environmentVariables:
CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 12 2013"
- job: windows_mingw_amd64
displayName: 'Windows (MinGW; amd64)'
pool: Hosted
steps:
- powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1'
displayName: Setup
env:
TEMP: $(Agent.TempDirectory)
ARCH: amd64
- template: ci/powershell.yml
parameters:
environmentVariables:
CMAKE_OPTIONS: -G"MinGW Makefiles"
PATH: $(Agent.TempDirectory)\mingw64\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin
- job: windows_mingw_x86
displayName: 'Windows (MinGW; x86)'
pool: Hosted
steps:
- powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1'
displayName: Setup
workingDirectory: '$(Build.BinariesDirectory)'
env:
TEMP: $(Agent.TempDirectory)
ARCH: x86
- template: ci/powershell.yml
parameters:
environmentVariables:
CMAKE_OPTIONS: -G"MinGW Makefiles"
PATH: $(Agent.TempDirectory)\mingw32\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin
# These are the steps used for building on machines with bash.
steps:
- bash: . '$(Build.SourcesDirectory)/ci/build.sh'
displayName: Build
workingDirectory: '$(Build.BinariesDirectory)'
env: ${{ parameters.environmentVariables }}
- bash: . '$(Build.SourcesDirectory)/ci/test.sh'
displayName: Test
workingDirectory: '$(Build.BinariesDirectory)'
env: ${{ parameters.environmentVariables }}
- task: PublishTestResults@2
displayName: Publish Test Results
condition: succeededOrFailed()
inputs:
testResultsFiles: 'results_*.xml'
searchFolder: '$(Build.BinariesDirectory)'
mergeTestResults: true
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
if ($Env:SOURCE_DIR) { $SourceDirectory = $Env:SOURCE_DIR } else { $SourceDirectory = Split-Path (Split-Path $MyInvocation.MyCommand.Path -Parent) -Parent }
$BuildDirectory = $(Get-Location).Path
Write-Host "Source directory: ${SourceDirectory}"
Write-Host "Build directory: ${BuildDirectory}"
Write-Host ""
Write-Host "Operating system version:"
Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, BuildNumber, OSArchitecture | Format-List
Write-Host "PATH: ${Env:PATH}"
Write-Host ""
Write-Host "##############################################################################"
Write-Host "## Configuring build environment"
Write-Host "##############################################################################"
Invoke-Expression "cmake ${SourceDirectory} -DBUILD_EXAMPLES=ON ${Env:CMAKE_OPTIONS}"
if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) }
Write-Host ""
Write-Host "##############################################################################"
Write-Host "## Building libgit2"
Write-Host "##############################################################################"
cmake --build .
if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) }
#!/usr/bin/env bash
#
# Environment variables:
#
# SOURCE_DIR: Set to the directory of the libgit2 source (optional)
# If not set, it will be derived relative to this script.
set -e
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
BUILD_DIR=$(pwd)
CC=${CC:-cc}
indent() { sed "s/^/ /"; }
echo "Source directory: ${SOURCE_DIR}"
echo "Build directory: ${BUILD_DIR}"
echo ""
echo "Operating system version:"
uname -a 2>&1 | indent
echo "CMake version:"
cmake --version 2>&1 | indent
echo "Compiler version:"
$CC --version 2>&1 | indent
echo ""
echo "##############################################################################"
echo "## Configuring build environment"
echo "##############################################################################"
echo cmake ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS}
cmake ${SOURCE_DIR} -DENABLE_WERROR=ON -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS}
echo ""
echo "##############################################################################"
echo "## Building libgit2"
echo "##############################################################################"
cmake --build .
#!/bin/bash
set -e
# Only run this on our branches
echo "Branch: $TRAVIS_BRANCH | Pull request: $TRAVIS_PULL_REQUEST | Slug: $TRAVIS_REPO_SLUG"
if [ "$TRAVIS_BRANCH" != "master" -o "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_REPO_SLUG" != "libgit2/libgit2" ];
then
echo "Only analyzing the 'master' brach of the main repository."
exit 0
fi
set -e
# Environment check
[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
BUILD_DIR=$(pwd)
case $(uname -m) in
i?86) BITS=32 ;;
amd64|x86_64) BITS=64 ;;
......@@ -32,31 +28,29 @@ if [ ! -d "$TOOL_BASE" ]; then
ln -s "$TOOL_DIR" "$TOOL_BASE"/cov-analysis
fi
cp script/user_nodefs.h "$TOOL_BASE"/cov-analysis/config/user_nodefs.h
cp "${SOURCE_DIR}/script/user_nodefs.h" "$TOOL_BASE"/cov-analysis/config/user_nodefs.h
COV_BUILD="$TOOL_BASE/cov-analysis/bin/cov-build"
# Configure and build
rm -rf _build
mkdir _build
cd _build
cmake .. -DTHREADSAFE=ON
cmake ${SOURCE_DIR}
COVERITY_UNSUPPORTED=1 \
$COV_BUILD --dir cov-int \
cmake --build .
# Upload results
tar czf libgit2.tgz cov-int
SHA=$(git rev-parse --short HEAD)
SHA=$(cd ${SOURCE_DIR} && git rev-parse --short HEAD)
HTML="$(curl \
--silent \
--write-out "\n%{http_code}" \
--form token="$COVERITY_TOKEN" \
--form email=bs@github.com \
--form email=libgit2@gmail.com \
--form file=@libgit2.tgz \
--form version="$SHA" \
--form description="Travis build" \
--form description="libgit2 build" \
https://scan.coverity.com/builds?project=libgit2)"
# Body is everything up to the last line
BODY="$(echo "$HTML" | head -n-1)"
......@@ -65,7 +59,7 @@ STATUS_CODE="$(echo "$HTML" | tail -n1)"
echo "${BODY}"
if [ "${STATUS_CODE}" != "201" ]; then
if [ "${STATUS_CODE}" != "200" -a "${STATUS_CODE}" != "201" ]; then
echo "Received error code ${STATUS_CODE} from Coverity"
exit 1
fi
# These are the steps used in a container-based build in VSTS.
steps:
- task: docker@0
displayName: Build
inputs:
action: 'Run an image'
imageName: ${{ parameters.imageName }}
volumes: |
$(Build.SourcesDirectory):/src
$(Build.BinariesDirectory):/build
envVars: ${{ parameters.environmentVariables }}
workDir: '/build'
containerCommand: '/src/ci/build.sh'
detached: false
- task: docker@0
displayName: Test
inputs:
action: 'Run an image'
imageName: ${{ parameters.imageName }}
volumes: |
$(Build.SourcesDirectory):/src
$(Build.BinariesDirectory):/build
envVars: ${{ parameters.environmentVariables }}
workDir: '/build'
containerCommand: '/src/ci/test.sh'
detached: false
- task: publishtestresults@2
displayName: Publish Test Results
condition: succeededOrFailed()
inputs:
testResultsFiles: 'results_*.xml'
searchFolder: '$(Build.BinariesDirectory)'
mergeTestResults: true
resources:
- repo: self
jobs:
- job: coverity
displayName: 'Coverity'
pool:
vmImage: 'Ubuntu 16.04'
steps:
- task: Docker@0
displayName: Build
inputs:
action: 'Run an image'
imageName: 'libgit2/trusty-openssl:latest'
volumes: |
$(Build.SourcesDirectory):/src
$(Build.BinariesDirectory):/build
envVars: |
COVERITY_TOKEN=$(COVERITY_TOKEN)
workDir: '/build'
containerCommand: '/src/ci/coverity.sh'
detached: false
# These are the steps used for building on machines with PowerShell.
steps:
- powershell: . '$(Build.SourcesDirectory)\ci\build.ps1'
displayName: Build
workingDirectory: '$(Build.BinariesDirectory)'
env: ${{ parameters.environmentVariables }}
- powershell: . '$(Build.SourcesDirectory)\ci\test.ps1'
displayName: Test
workingDirectory: '$(Build.BinariesDirectory)'
env: ${{ parameters.environmentVariables }}
- task: PublishTestResults@2
displayName: Publish Test Results
condition: succeededOrFailed()
inputs:
testResultsFiles: 'results_*.xml'
searchFolder: '$(Build.BinariesDirectory)'
mergeTestResults: true
#!/bin/sh
set -e
set -x
TMPDIR=${TMPDIR:-/tmp}
if [ -z "$SKIP_APT" ]; then
apt-get update
apt-get -y install build-essential pkg-config clang cmake openssl libssl-dev libssh2-1-dev libcurl4-gnutls-dev openssh-server
fi
mkdir -p /var/run/sshd
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem");
Write-Host "##############################################################################"
Write-Host "## Downloading mingw"
Write-Host "##############################################################################"
if ($env:ARCH -eq "amd64") {
$mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-x86_64-8.1.0-release-win32-seh-rt_v6-rev0.zip"
$platform = "x86_64"
} else {
$mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip"
$platform = "x86"
}
$wc = New-Object net.webclient
$wc.Downloadfile($mingw_uri, "${Env:TEMP}/mingw-${Env:ARCH}.zip")
[System.IO.Compression.ZipFile]::ExtractToDirectory("${Env:TEMP}/mingw-${Env:ARCH}.zip", $Env:TEMP)
#!/bin/sh
set -x
brew update
brew install pkgconfig zlib curl openssl libssh2
ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$SourceDir = Split-Path (Split-Path (Get-Variable MyInvocation).Value.MyCommand.Path)
$BuildDir = Get-Location
$global:Success = $true
if ($Env:SKIP_TESTS) { exit }
# Ask ctest what it would run if we were to invoke it directly. This lets
# us manage the test configuration in a single place (tests/CMakeLists.txt)
# instead of running clar here as well. But it allows us to wrap our test
# harness with a leak checker like valgrind. Append the option to write
# JUnit-style XML files.
function run_test {
$TestName = $args[0]
$TestCommand = (ctest -N -V -R "^$TestName$") -join "`n" -replace "(?ms).*\n^[0-9]*: Test command: ","" -replace "\n.*",""
$TestCommand += " -r${BuildDir}\results_${TestName}.xml"
Write-Host $TestCommand
Invoke-Expression $TestCommand
if ($LastExitCode -ne 0) { $global:Success = $false }
}
Write-Host "##############################################################################"
Write-Host "## Configuring test environment"
Write-Host "##############################################################################"
if (-not $Env:SKIP_PROXY_TESTS) {
Write-Host ""
Write-Host "Starting HTTP proxy..."
Invoke-WebRequest -Method GET -Uri https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -OutFile poxyproxy.jar
javaw -jar poxyproxy.jar -d --port 8080 --credentials foo:bar
}
Write-Host ""
Write-Host "##############################################################################"
Write-Host "## Running (offline) tests"
Write-Host "##############################################################################"
run_test offline
if (-not $Env:SKIP_ONLINE_TESTS) {
Write-Host ""
Write-Host "##############################################################################"
Write-Host "## Running (online) tests"
Write-Host "##############################################################################"
run_test online
}
if (-not $Env:SKIP_PROXY_TESTS) {
Write-Host ""
Write-Host "Running proxy tests"
Write-Host ""
$Env:GITTEST_REMOTE_PROXY_URL="localhost:8080"
$Env:GITTEST_REMOTE_PROXY_USER="foo"
$Env:GITTEST_REMOTE_PROXY_PASS="bar"
run_test proxy
taskkill /F /IM javaw.exe
}
if (-Not $global:Success) { exit 1 }
#!/usr/bin/env bash
set -e
if [ -n "$SKIP_TESTS" ]; then
exit 0
fi
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
BUILD_DIR=$(pwd)
TMPDIR=${TMPDIR:-/tmp}
USER=${USER:-$(whoami)}
SUCCESS=1
VALGRIND="valgrind --leak-check=full --show-reachable=yes --error-exitcode=125 --num-callers=50 --suppressions=\"$SOURCE_DIR/libgit2_clar.supp\""
LEAKS="MallocStackLogging=1 MallocScribble=1 leaks -quiet -atExit -- nohup"
cleanup() {
echo "Cleaning up..."
if [ ! -z "$GITDAEMON_DIR" -a -f "${GITDAEMON_DIR}/pid" ]; then
echo "Stopping git daemon..."
kill $(cat "${GITDAEMON_DIR}/pid")
fi
if [ ! -z "$SSHD_DIR" -a -f "${SSHD_DIR}/pid" ]; then
echo "Stopping SSH..."
kill $(cat "${SSHD_DIR}/pid")
fi
echo "Done."
}
failure() {
echo "Test exited with code: $1"
SUCCESS=0
}
# Ask ctest what it would run if we were to invoke it directly. This lets
# us manage the test configuration in a single place (tests/CMakeLists.txt)
# instead of running clar here as well. But it allows us to wrap our test
# harness with a leak checker like valgrind. Append the option to write
# JUnit-style XML files.
run_test() {
TEST_CMD=$(ctest -N -V -R "^${1}$" | sed -n 's/^[0-9]*: Test command: //p')
TEST_CMD="${TEST_CMD} -r${BUILD_DIR}/results_${1}.xml"
if [ "$LEAK_CHECK" = "valgrind" ]; then
RUNNER="$VALGRIND $TEST_CMD"
elif [ "$LEAK_CHECK" = "leaks" ]; then
RUNNER="$LEAKS $TEST_CMD"
else
RUNNER="$TEST_CMD"
fi
eval $RUNNER || failure
}
# Configure the test environment; run them early so that we're certain
# that they're started by the time we need them.
echo "##############################################################################"
echo "## Configuring test environment"
echo "##############################################################################"
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
echo "Starting git daemon..."
GITDAEMON_DIR=`mktemp -d ${TMPDIR}/gitdaemon.XXXXXXXX`
git init --bare "${GITDAEMON_DIR}/test.git"
git daemon --listen=localhost --export-all --enable=receive-pack --pid-file="${GITDAEMON_DIR}/pid" --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null &
fi
if [ -z "$SKIP_PROXY_TESTS" ]; then
echo "Starting HTTP proxy..."
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar
java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar >/dev/null 2>&1 &
fi
if [ -z "$SKIP_SSH_TESTS" ]; then
echo "Starting ssh daemon..."
HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX`
git init --bare "${SSHD_DIR}/test.git"
cat >"${SSHD_DIR}/sshd_config" <<-EOF
Port 2222
ListenAddress 0.0.0.0
Protocol 2
HostKey ${SSHD_DIR}/id_rsa
PidFile ${SSHD_DIR}/pid
AuthorizedKeysFile ${HOME}/.ssh/authorized_keys
LogLevel DEBUG
RSAAuthentication yes
PasswordAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
StrictModes no
# Required here as sshd will simply close connection otherwise
UsePAM no
EOF
ssh-keygen -t rsa -f "${SSHD_DIR}/id_rsa" -N "" -q
/usr/sbin/sshd -f "${SSHD_DIR}/sshd_config" -E "${SSHD_DIR}/log"
# Set up keys
mkdir "${HOME}/.ssh"
ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa" -N "" -q
cat "${HOME}/.ssh/id_rsa.pub" >>"${HOME}/.ssh/authorized_keys"
while read algorithm key comment; do
echo "[localhost]:2222 $algorithm $key" >>"${HOME}/.ssh/known_hosts"
done <"${SSHD_DIR}/id_rsa.pub"
# Get the fingerprint for localhost and remove the colons so we can
# parse it as a hex number. Older versions have a different output
# format.
if [[ $(ssh -V 2>&1) == OpenSSH_6* ]]; then
SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
else
SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
fi
fi
# Run the tests that do not require network connectivity.
if [ -z "$SKIP_OFFLINE_TESTS" ]; then
echo ""
echo "##############################################################################"
echo "## Running (offline) tests"
echo "##############################################################################"
run_test offline
fi
if [ -z "$SKIP_ONLINE_TESTS" ]; then
# Run the various online tests. The "online" test suite only includes the
# default online tests that do not require additional configuration. The
# "proxy" and "ssh" test suites require further setup.
echo ""
echo "##############################################################################"
echo "## Running (online) tests"
echo "##############################################################################"
run_test online
fi
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
echo ""
echo "Running gitdaemon tests"
echo ""
export GITTEST_REMOTE_URL="git://localhost/test.git"
run_test gitdaemon
unset GITTEST_REMOTE_URL
fi
if [ -z "$SKIP_PROXY_TESTS" ]; then
echo ""
echo "Running proxy tests"
echo ""
export GITTEST_REMOTE_PROXY_URL="localhost:8080"
export GITTEST_REMOTE_PROXY_USER="foo"
export GITTEST_REMOTE_PROXY_PASS="bar"
run_test proxy
unset GITTEST_REMOTE_PROXY_URL
unset GITTEST_REMOTE_PROXY_USER
unset GITTEST_REMOTE_PROXY_PASS
fi
if [ -z "$SKIP_SSH_TESTS" ]; then
echo ""
echo "Running ssh tests"
echo ""
export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git"
export GITTEST_REMOTE_USER=$USER
export GITTEST_REMOTE_SSH_KEY="${HOME}/.ssh/id_rsa"
export GITTEST_REMOTE_SSH_PUBKEY="${HOME}/.ssh/id_rsa.pub"
export GITTEST_REMOTE_SSH_PASSPHRASE=""
export GITTEST_REMOTE_SSH_FINGERPRINT="${SSH_FINGERPRINT}"
run_test ssh
unset GITTEST_REMOTE_URL
unset GITTEST_REMOTE_USER
unset GITTEST_REMOTE_SSH_KEY
unset GITTEST_REMOTE_SSH_PUBKEY
unset GITTEST_REMOTE_SSH_PASSPHRASE
unset GITTEST_REMOTE_SSH_FINGERPRINT
fi
cleanup
if [ "$SUCCESS" -ne "1" ]; then
echo "Some tests failed."
exit 1
fi
echo "Success."
exit 0
......@@ -7,10 +7,10 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.27.5"
#define LIBGIT2_VERSION "0.27.6"
#define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 27
#define LIBGIT2_VER_REVISION 5
#define LIBGIT2_VER_REVISION 6
#define LIBGIT2_VER_PATCH 0
#define LIBGIT2_SOVERSION 27
......
......@@ -47,3 +47,28 @@
...
fun:__check_pf
}
{
ignore-curl-global-init
Memcheck:Leak
...
fun:curl_global_init
}
{
ignore-libssh2-gcrypt-leak
Memcheck:Leak
...
fun:gcry_control
obj:*libssh2.so*
}
{
ignore-noai6ai_cached-double-free
Memcheck:Free
fun:free
fun:__libc_freeres
...
fun:exit
...
}
#!/bin/sh
set -e
cd `dirname "$0"`/..
if [ "$ARCH" = "i686" ]; then
f=i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
if ! [ -e $f ]; then
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/threads-win32/sjlj/$f
fi
7z x $f > /dev/null
export PATH=`pwd`/mingw32/bin:$PATH
else
f=x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z
if ! [ -e $f ]; then
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/$f
fi
7z x $f > /dev/null
export PATH=`pwd`/mingw64/bin:$PATH
fi
cd build
gcc --version
cmake --version
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D BUILD_EXAMPLES=ON .. -G"$GENERATOR"
cmake --build . --config RelWithDebInfo
#!/bin/sh
set -x
if [ -n "$COVERITY" ];
then
./script/coverity.sh;
exit $?;
fi
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export PKG_CONFIG_PATH=$(ls -d /usr/local/Cellar/{curl,zlib}/*/lib/pkgconfig | paste -s -d':' -)
# Set up a ramdisk for us to put our test data on to speed up tests on macOS
export CLAR_TMP="$HOME"/_clar_tmp
mkdir -p $CLAR_TMP
# 5*2M sectors aka ~5GB of space
device=$(hdiutil attach -nomount ram://$((5 * 2 * 1024 * 1024)))
newfs_hfs $device
mount -t hfs $device $CLAR_TMP
fi
# Should we ask Travis to cache this file?
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar || exit $?
# Run this early so we know it's ready by the time we need it
java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar &
mkdir _build
cd _build
# shellcheck disable=SC2086
cmake .. -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
make -j2 install || exit $?
# If this platform doesn't support test execution, bail out now
if [ -n "$SKIP_TESTS" ];
then
exit $?;
fi
# Create a test repo which we can use for the online::push tests
mkdir "$HOME"/_temp
git init --bare "$HOME"/_temp/test.git
git daemon --listen=localhost --export-all --enable=receive-pack --base-path="$HOME"/_temp "$HOME"/_temp 2>/dev/null &
export GITTEST_REMOTE_URL="git://localhost/test.git"
# Run the test suite
ctest -V -R libgit2_clar || exit $?
# Now that we've tested the raw git protocol, let's set up ssh to we
# can do the push tests over it
killall git-daemon
# Set up sshd
mkdir ~/sshd/
cat >~/sshd/sshd_config<<-EOF
Port 2222
ListenAddress 0.0.0.0
Protocol 2
HostKey ${HOME}/sshd/id_rsa
PidFile ${HOME}/sshd/pid
RSAAuthentication yes
PasswordAuthentication yes
PubkeyAuthentication yes
ChallengeResponseAuthentication no
# Required here as sshd will simply close connection otherwise
UsePAM no
EOF
ssh-keygen -t rsa -f ~/sshd/id_rsa -N "" -q
/usr/sbin/sshd -f ~/sshd/sshd_config
# Set up keys
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
while read algorithm key comment; do
echo "[localhost]:2222 $algorithm $key" >>~/.ssh/known_hosts
done <~/sshd/id_rsa.pub
# Get the fingerprint for localhost and remove the colons so we can parse it as
# a hex number. The Mac version is newer so it has a different output format.
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
else
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
fi
# Use the SSH server
export GITTEST_REMOTE_URL="ssh://localhost:2222/$HOME/_temp/test.git"
export GITTEST_REMOTE_USER=$USER
export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa"
export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub"
export GITTEST_REMOTE_SSH_PASSPHRASE=""
ctest -V -R libgit2_clar-ssh || exit $?
# Use the proxy we started at the beginning
export GITTEST_REMOTE_PROXY_URL="localhost:8080"
export GITTEST_REMOTE_PROXY_USER="foo"
export GITTEST_REMOTE_PROXY_PASS="bar"
ctest -V -R libgit2_clar-proxy_credentials || exit $?
kill $(cat "$HOME/sshd/pid")
#!/bin/sh
set -x
brew update
brew install zlib
brew install curl
brew install openssl
brew install libssh2
......@@ -443,7 +443,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
while (eoln < buffer_end && *eoln != '\n')
++eoln;
if (git__prefixcmp(buffer, "encoding ") == 0) {
if (git__prefixncmp(buffer, buffer_end - buffer, "encoding ") == 0) {
buffer += strlen("encoding ");
commit->message_encoding = git__strndup(buffer, eoln - buffer);
......
......@@ -171,7 +171,9 @@ static int commit_quick_parse(
buffer--;
}
if ((buffer == committer_start) || (git__strtol64(&commit_time, (char *)(buffer + 1), NULL, 10) < 0))
if ((buffer == committer_start) ||
(git__strntol64(&commit_time, (char *)(buffer + 1),
buffer_end - buffer + 1, NULL, 10) < 0))
return commit_error(commit, "cannot parse commit time");
commit->time = commit_time;
......
......@@ -1300,7 +1300,7 @@ int git_config_parse_int64(int64_t *out, const char *value)
const char *num_end;
int64_t num;
if (!value || git__strtol64(&num, value, &num_end, 0) < 0)
if (!value || git__strntol64(&num, value, strlen(value), &num_end, 0) < 0)
goto fail_parse;
switch (*num_end) {
......
......@@ -2206,7 +2206,7 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
for (i = 0; i < 3; i++) {
int64_t tmp;
if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 ||
if (git__strntol64(&tmp, buffer, size, &endptr, 8) < 0 ||
!endptr || endptr == buffer || *endptr ||
tmp < 0 || tmp > UINT32_MAX) {
index_entry_reuc_free(lost);
......
......@@ -1384,8 +1384,8 @@ static int git_odb_stream__invalid_length(
{
giterr_set(GITERR_ODB,
"cannot %s - "
"Invalid length. %"PRIdZ" was expected. The "
"total size of the received chunks amounts to %"PRIdZ".",
"Invalid length. %"PRId64" was expected. The "
"total size of the received chunks amounts to %"PRId64".",
action, stream->declared_size, stream->received_bytes);
return -1;
......
......@@ -152,7 +152,7 @@ GIT_INLINE(int) rebase_readint(
if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
return error;
if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) {
if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) {
giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename);
return -1;
}
......
......@@ -128,7 +128,8 @@ static int try_parse_numeric(int *n, const char *curly_braces_content)
int32_t content;
const char *end_ptr;
if (git__strtol32(&content, curly_braces_content, &end_ptr, 10) < 0)
if (git__strntol32(&content, curly_braces_content, strlen(curly_braces_content),
&end_ptr, 10) < 0)
return -1;
if (*end_ptr != '\0')
......@@ -578,7 +579,7 @@ static int extract_how_many(int *n, const char *spec, size_t *pos)
} while (spec[(*pos)] == kind && kind == '~');
if (git__isdigit(spec[*pos])) {
if (git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0)
if (git__strntol32(&parsed, spec + *pos, strlen(spec + *pos), &end_ptr, 10) < 0)
return GIT_EINVALIDSPEC;
accumulated += (parsed - 1);
......
......@@ -231,7 +231,8 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
const char *time_start = email_end + 2;
const char *time_end;
if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) {
if (git__strntol64(&sig->when.time, time_start,
buffer_end - time_start, &time_end, 10) < 0) {
git__free(sig->name);
git__free(sig->email);
sig->name = sig->email = NULL;
......@@ -246,8 +247,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
tz_start = time_end + 1;
if ((tz_start[0] != '-' && tz_start[0] != '+') ||
git__strtol32(&offset, tz_start + 1, &tz_end, 10) < 0) {
//malformed timezone, just assume it's zero
git__strntol32(&offset, tz_start + 1,
buffer_end - tz_start + 1, &tz_end, 10) < 0) {
/* malformed timezone, just assume it's zero */
offset = 0;
}
......
......@@ -330,7 +330,7 @@ int git_curl_stream_new(git_stream **out, const char *host, const char *port)
return -1;
}
if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) {
if ((error = git__strntol32(&iport, port, strlen(port), NULL, 10)) < 0) {
git__free(st);
return error;
}
......
......@@ -70,10 +70,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
static const char *tag_types[] = {
NULL, "commit\n", "tree\n", "blob\n", "tag\n"
};
unsigned int i;
size_t text_len, alloc_len;
char *search;
const char *search;
unsigned int i;
if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
return tag_error("object field invalid");
......@@ -138,8 +137,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
tag->message = NULL;
if (buffer < buffer_end) {
/* If we're not at the end of the header, search for it */
if( *buffer != '\n' ) {
search = strstr(buffer, "\n\n");
if(*buffer != '\n') {
search = git__memmem(buffer, buffer_end - buffer,
"\n\n", 2);
if (search)
buffer = search + 1;
else
......
......@@ -45,6 +45,11 @@ GIT_INLINE(int) git_smart__reset_stream(transport_smart *t, bool close_subtransp
t->current_stream = NULL;
}
if (t->url) {
git__free(t->url);
t->url = NULL;
}
if (close_subtransport &&
t->wrapped->close(t->wrapped) < 0)
return -1;
......
......@@ -391,7 +391,7 @@ static int parse_len(size_t *out, const char *line, size_t linelen)
}
}
if ((error = git__strtol32(&len, num, &num_end, 16)) < 0)
if ((error = git__strntol32(&len, num, PKT_LEN_SIZE, &num_end, 16)) < 0)
return error;
if (len < 0)
......
......@@ -761,7 +761,8 @@ static int winhttp_connect(
t->connection = NULL;
/* Prepare port */
if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
if (git__strntol32(&port, t->connection_data.port,
strlen(t->connection_data.port), NULL, 10) < 0)
return -1;
/* Prepare host */
......
......@@ -91,7 +91,7 @@ static int read_tree_internal(git_tree_cache **out,
return -1;
/* Blank-terminated ASCII decimal number of entries in this tree */
if (git__strtol32(&count, buffer, &buffer, 10) < 0)
if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0)
goto corrupted;
tree->entry_count = count;
......@@ -100,7 +100,7 @@ static int read_tree_internal(git_tree_cache **out,
goto corrupted;
/* Number of children of the tree, newline-terminated */
if (git__strtol32(&count, buffer, &buffer, 10) < 0 || count < 0)
if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0 || count < 0)
goto corrupted;
tree->children_count = count;
......
......@@ -68,12 +68,6 @@ int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
return 0;
}
int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
{
return git__strntol64(result, nptr, (size_t)-1, endptr, base);
}
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
{
const char *p;
......@@ -132,10 +126,20 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
v = c - 'A' + 10;
if (v >= base)
break;
nn = n * base + (neg ? -v : v);
if ((!neg && nn < n) || (neg && nn > n))
v = neg ? -v : v;
if (n > INT64_MAX / base || n < INT64_MIN / base) {
ovfl = 1;
n = nn;
/* Keep on iterating until the end of this number */
continue;
}
nn = n * base;
if ((v > 0 && nn > INT64_MAX - v) ||
(v < 0 && nn < INT64_MIN - v)) {
ovfl = 1;
/* Keep on iterating until the end of this number */
continue;
}
n = nn + v;
}
Return:
......@@ -156,28 +160,26 @@ Return:
return 0;
}
int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base)
{
return git__strntol32(result, nptr, (size_t)-1, endptr, base);
}
int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
{
int error;
const char *tmp_endptr;
int32_t tmp_int;
int64_t tmp_long;
int error;
if ((error = git__strntol64(&tmp_long, nptr, nptr_len, endptr, base)) < 0)
if ((error = git__strntol64(&tmp_long, nptr, nptr_len, &tmp_endptr, base)) < 0)
return error;
tmp_int = tmp_long & 0xFFFFFFFF;
if (tmp_int != tmp_long) {
giterr_set(GITERR_INVALID, "failed to convert: '%s' is too large", nptr);
int len = tmp_endptr - nptr;
giterr_set(GITERR_INVALID, "failed to convert: '%.*s' is too large", len, nptr);
return -1;
}
*result = tmp_int;
if (endptr)
*endptr = tmp_endptr;
return error;
}
......@@ -355,6 +357,47 @@ size_t git__linenlen(const char *buffer, size_t buffer_len)
return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
}
/*
* Adapted Not So Naive algorithm from http://www-igm.univ-mlv.fr/~lecroq/string/
*/
const void * git__memmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen)
{
const char *h, *n;
size_t j, k, l;
if (needlelen > haystacklen || !haystacklen || !needlelen)
return NULL;
h = (const char *) haystack,
n = (const char *) needle;
if (needlelen == 1)
return memchr(haystack, *n, haystacklen);
if (n[0] == n[1]) {
k = 2;
l = 1;
} else {
k = 1;
l = 2;
}
j = 0;
while (j <= haystacklen - needlelen) {
if (n[1] != h[j + 1]) {
j += k;
} else {
if (memcmp(n + 2, h + j + 2, needlelen - 2) == 0 &&
n[0] == h[j])
return h + j;
j += l;
}
}
return NULL;
}
void git__hexdump(const char *buffer, size_t len)
{
static const size_t LINE_WIDTH = 16;
......
......@@ -193,9 +193,7 @@ GIT_INLINE(int) git__signum(int val)
return ((val > 0) - (val < 0));
}
extern int git__strtol32(int32_t *n, const char *buff, const char **end_buf, int base);
extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
extern int git__strtol64(int64_t *n, const char *buff, const char **end_buf, int base);
extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
......@@ -248,6 +246,9 @@ GIT_INLINE(const void *) git__memrchr(const void *s, int c, size_t n)
return NULL;
}
extern const void * git__memmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
typedef int (*git__tsort_cmp)(const void *a, const void *b);
extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);
......
......@@ -52,12 +52,8 @@ IF (MSVC_IDE)
SET_SOURCE_FILES_PROPERTIES("precompiled.c" COMPILE_FLAGS "/Ycprecompiled.h")
ENDIF ()
IF (USE_HTTPS)
ADD_TEST(libgit2_clar "${libgit2_BINARY_DIR}/libgit2_clar" -ionline -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
ELSE ()
ADD_TEST(libgit2_clar "${libgit2_BINARY_DIR}/libgit2_clar" -v -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
ENDIF ()
# Add additional test targets that require special setup
ADD_TEST(libgit2_clar-proxy_credentials "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::clone::proxy_credentials_in_url -sonline::clone::proxy_credentials_request)
ADD_TEST(libgit2_clar-ssh "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths)
ADD_TEST(offline "${libgit2_BINARY_DIR}/libgit2_clar" -v -xonline)
ADD_TEST(online "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline)
ADD_TEST(gitdaemon "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push)
ADD_TEST(ssh "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths)
ADD_TEST(proxy "${libgit2_BINARY_DIR}/libgit2_clar" -v -sonline::clone::proxy_credentials_in_url -sonline::clone::proxy_credentials_request)
#include "clar_libgit2.h"
#include "buffer.h"
#if defined(GIT_ARCH_64)
#define TOOBIG 0xffffffffffffff00
/*
* We want to use some ridiculous size that `malloc` will fail with
* but that does not otherwise interfere with testing. On Linux, choose
* a number that is large enough to fail immediately but small enough
* that valgrind doesn't believe it to erroneously be a negative number.
* On macOS, choose a number that is large enough to fail immediately
* without having libc print warnings to stderr.
*/
#if defined(GIT_ARCH_64) && defined(__linux__)
# define TOOBIG 0x0fffffffffffffff
#elif defined(__linux__)
# define TOOBIG 0x0fffffff
#elif defined(GIT_ARCH_64)
# define TOOBIG 0xffffffffffffff00
#else
#define TOOBIG 0xffffff00
# define TOOBIG 0xffffff00
#endif
/**
......
......@@ -95,9 +95,6 @@ static const char *
fixture_path(const char *base, const char *fixture_name);
struct clar_error {
const char *test;
int test_number;
const char *suite;
const char *file;
int line_number;
const char *error_msg;
......@@ -106,11 +103,34 @@ struct clar_error {
struct clar_error *next;
};
static struct {
int argc;
char **argv;
struct clar_explicit {
size_t suite_idx;
const char *filter;
struct clar_explicit *next;
};
struct clar_report {
const char *test;
int test_number;
const char *suite;
enum cl_test_status status;
struct clar_error *errors;
struct clar_error *last_error;
struct clar_report *next;
};
struct clar_summary {
const char *filename;
FILE *fp;
};
static struct {
enum cl_test_status test_status;
const char *active_test;
const char *active_suite;
......@@ -124,8 +144,15 @@ static struct {
int exit_on_error;
int report_suite_names;
struct clar_error *errors;
struct clar_error *last_error;
int write_summary;
const char *summary_filename;
struct clar_summary *summary;
struct clar_explicit *explicit;
struct clar_explicit *last_explicit;
struct clar_report *reports;
struct clar_report *last_report;
void (*local_cleanup)(void *);
void *local_cleanup_payload;
......@@ -155,7 +182,7 @@ struct clar_suite {
/* From clar_print_*.c */
static void clar_print_init(int test_count, int suite_count, const char *suite_names);
static void clar_print_shutdown(int test_count, int suite_count, int error_count);
static void clar_print_error(int num, const struct clar_error *error);
static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error);
static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed);
static void clar_print_onsuite(const char *suite_name, int suite_index);
static void clar_print_onabort(const char *msg, ...);
......@@ -164,6 +191,10 @@ static void clar_print_onabort(const char *msg, ...);
static void clar_unsandbox(void);
static int clar_sandbox(void);
/* From summary.h */
static struct clar_summary *clar_summary_init(const char *filename);
static int clar_summary_shutdown(struct clar_summary *fp);
/* Load the declarations for the test suite */
#include "clar.suite"
......@@ -186,21 +217,29 @@ void cl_trace_register(cl_trace_cb *cb, void *payload)
/* Core test functions */
static void
clar_report_errors(void)
clar_report_errors(struct clar_report *report)
{
struct clar_error *error;
int i = 1;
struct clar_error *error, *next;
error = _clar.errors;
while (error != NULL) {
next = error->next;
clar_print_error(i++, error);
free(error->description);
free(error);
error = next;
}
for (error = report->errors; error; error = error->next)
clar_print_error(i++, _clar.last_report, error);
}
static void
clar_report_all(void)
{
struct clar_report *report;
struct clar_error *error;
int i = 1;
for (report = _clar.reports; report; report = report->next) {
if (report->status != CL_TEST_FAILURE)
continue;
_clar.errors = _clar.last_error = NULL;
for (error = report->errors; error; error = error->next)
clar_print_error(i++, report, error);
}
}
static void
......@@ -209,7 +248,6 @@ clar_run_test(
const struct clar_func *initialize,
const struct clar_func *cleanup)
{
_clar.test_status = CL_TEST_OK;
_clar.trampoline_enabled = 1;
CL_TRACE(CL_TRACE__TEST__BEGIN);
......@@ -225,6 +263,9 @@ clar_run_test(
_clar.trampoline_enabled = 0;
if (_clar.last_report->status == CL_TEST_NOTRUN)
_clar.last_report->status = CL_TEST_OK;
if (_clar.local_cleanup != NULL)
_clar.local_cleanup(_clar.local_cleanup_payload);
......@@ -240,9 +281,9 @@ clar_run_test(
_clar.local_cleanup_payload = NULL;
if (_clar.report_errors_only) {
clar_report_errors();
clar_report_errors(_clar.last_report);
} else {
clar_print_ontest(test->name, _clar.tests_ran, _clar.test_status);
clar_print_ontest(test->name, _clar.tests_ran, _clar.last_report->status);
}
}
......@@ -251,6 +292,7 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
{
const struct clar_func *test = suite->tests;
size_t i, matchlen;
struct clar_report *report;
if (!suite->enabled)
return;
......@@ -283,6 +325,21 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
continue;
_clar.active_test = test[i].name;
report = calloc(1, sizeof(struct clar_report));
report->suite = _clar.active_suite;
report->test = _clar.active_test;
report->test_number = _clar.tests_ran;
report->status = CL_TEST_NOTRUN;
if (_clar.reports == NULL)
_clar.reports = report;
if (_clar.last_report != NULL)
_clar.last_report->next = report;
_clar.last_report = report;
clar_run_test(&test[i], &suite->initialize, &suite->cleanup);
if (_clar.exit_on_error && _clar.total_errors)
......@@ -298,13 +355,14 @@ clar_usage(const char *arg)
{
printf("Usage: %s [options]\n\n", arg);
printf("Options:\n");
printf(" -sname\tRun only the suite with `name` (can go to individual test name)\n");
printf(" -iname\tInclude the suite with `name`\n");
printf(" -xname\tExclude the suite with `name`\n");
printf(" -v \tIncrease verbosity (show suite names)\n");
printf(" -q \tOnly report tests that had an error\n");
printf(" -Q \tQuit as soon as a test fails\n");
printf(" -l \tPrint suite names\n");
printf(" -sname Run only the suite with `name` (can go to individual test name)\n");
printf(" -iname Include the suite with `name`\n");
printf(" -xname Exclude the suite with `name`\n");
printf(" -v Increase verbosity (show suite names)\n");
printf(" -q Only report tests that had an error\n");
printf(" -Q Quit as soon as a test fails\n");
printf(" -l Print suite names\n");
printf(" -r[filename] Write summary file (to the optional filename)\n");
exit(-1);
}
......@@ -318,7 +376,7 @@ clar_parse_args(int argc, char **argv)
char *argument = argv[i];
if (argument[0] != '-' || argument[1] == '\0'
|| strchr("sixvqQl", argument[1]) == NULL) {
|| strchr("sixvqQlr", argument[1]) == NULL) {
clar_usage(argv[0]);
}
}
......@@ -359,7 +417,24 @@ clar_parse_args(int argc, char **argv)
_clar.report_suite_names = 1;
switch (action) {
case 's': _clar_suites[j].enabled = 1; clar_run_suite(&_clar_suites[j], argument); break;
case 's': {
struct clar_explicit *explicit =
calloc(1, sizeof(struct clar_explicit));
assert(explicit);
explicit->suite_idx = j;
explicit->filter = argument;
if (_clar.explicit == NULL)
_clar.explicit = explicit;
if (_clar.last_explicit != NULL)
_clar.last_explicit->next = explicit;
_clar_suites[j].enabled = 1;
_clar.last_explicit = explicit;
break;
}
case 'i': _clar_suites[j].enabled = 1; break;
case 'x': _clar_suites[j].enabled = 0; break;
}
......@@ -397,6 +472,12 @@ clar_parse_args(int argc, char **argv)
_clar.report_suite_names = 1;
break;
case 'r':
_clar.write_summary = 1;
_clar.summary_filename = *(argument + 2) ? (argument + 2) :
"summary.xml";
break;
default:
assert(!"Unexpected commandline argument!");
}
......@@ -412,23 +493,31 @@ clar_test_init(int argc, char **argv)
""
);
if (argc > 1)
clar_parse_args(argc, argv);
if (_clar.write_summary &&
!(_clar.summary = clar_summary_init(_clar.summary_filename))) {
clar_print_onabort("Failed to open the summary file\n");
exit(-1);
}
if (clar_sandbox() < 0) {
clar_print_onabort("Failed to sandbox the test runner.\n");
exit(-1);
}
_clar.argc = argc;
_clar.argv = argv;
}
int
clar_test_run(void)
{
if (_clar.argc > 1)
clar_parse_args(_clar.argc, _clar.argv);
if (!_clar.suites_ran) {
size_t i;
struct clar_explicit *explicit;
if (_clar.explicit) {
for (explicit = _clar.explicit; explicit; explicit = explicit->next)
clar_run_suite(&_clar_suites[explicit->suite_idx], explicit->filter);
} else {
for (i = 0; i < _clar_suite_count; ++i)
clar_run_suite(&_clar_suites[i], NULL);
}
......@@ -439,6 +528,9 @@ clar_test_run(void)
void
clar_test_shutdown(void)
{
struct clar_explicit *explicit, *explicit_next;
struct clar_report *report, *report_next;
clar_print_shutdown(
_clar.tests_ran,
(int)_clar_suite_count,
......@@ -446,6 +538,21 @@ clar_test_shutdown(void)
);
clar_unsandbox();
if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) {
clar_print_onabort("Failed to write the summary file\n");
exit(-1);
}
for (explicit = _clar.explicit; explicit; explicit = explicit_next) {
explicit_next = explicit->next;
free(explicit);
}
for (report = _clar.reports; report; report = report_next) {
report_next = report->next;
free(report);
}
}
int
......@@ -465,7 +572,7 @@ static void abort_test(void)
if (!_clar.trampoline_enabled) {
clar_print_onabort(
"Fatal error: a cleanup method raised an exception.");
clar_report_errors();
clar_report_errors(_clar.last_report);
exit(-1);
}
......@@ -475,7 +582,7 @@ static void abort_test(void)
void clar__skip(void)
{
_clar.test_status = CL_TEST_SKIP;
_clar.last_report->status = CL_TEST_SKIP;
_clar.total_skipped++;
abort_test();
}
......@@ -489,17 +596,14 @@ void clar__fail(
{
struct clar_error *error = calloc(1, sizeof(struct clar_error));
if (_clar.errors == NULL)
_clar.errors = error;
if (_clar.last_report->errors == NULL)
_clar.last_report->errors = error;
if (_clar.last_error != NULL)
_clar.last_error->next = error;
if (_clar.last_report->last_error != NULL)
_clar.last_report->last_error->next = error;
_clar.last_error = error;
_clar.last_report->last_error = error;
error->test = _clar.active_test;
error->test_number = _clar.tests_ran;
error->suite = _clar.active_suite;
error->file = file;
error->line_number = line;
error->error_msg = error_msg;
......@@ -508,7 +612,7 @@ void clar__fail(
error->description = strdup(description);
_clar.total_errors++;
_clar.test_status = CL_TEST_FAILURE;
_clar.last_report->status = CL_TEST_FAILURE;
if (should_abort)
abort_test();
......@@ -653,3 +757,4 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
#include "clar/fixtures.h"
#include "clar/fs.h"
#include "clar/print.h"
#include "clar/summary.h"
......@@ -12,13 +12,16 @@
enum cl_test_status {
CL_TEST_OK,
CL_TEST_FAILURE,
CL_TEST_SKIP
CL_TEST_SKIP,
CL_TEST_NOTRUN,
};
/** Setup clar environment */
void clar_test_init(int argc, char *argv[]);
int clar_test_run(void);
void clar_test_shutdown(void);
/** One shot setup & run */
int clar_test(int argc, char *argv[]);
const char *clar_sandbox_path(void);
......
......@@ -13,16 +13,16 @@ static void clar_print_shutdown(int test_count, int suite_count, int error_count
(void)error_count;
printf("\n\n");
clar_report_errors();
clar_report_all();
}
static void clar_print_error(int num, const struct clar_error *error)
static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error)
{
printf(" %d) Failure:\n", num);
printf("%s::%s [%s:%d]\n",
error->suite,
error->test,
report->suite,
report->test,
error->file,
error->line_number);
......@@ -44,6 +44,7 @@ static void clar_print_ontest(const char *test_name, int test_number, enum cl_te
case CL_TEST_OK: printf("."); break;
case CL_TEST_FAILURE: printf("F"); break;
case CL_TEST_SKIP: printf("S"); break;
case CL_TEST_NOTRUN: printf("N"); break;
}
fflush(stdout);
......
#include <stdio.h>
#include <time.h>
int clar_summary_close_tag(
struct clar_summary *summary, const char *tag, int indent)
{
const char *indt;
if (indent == 0) indt = "";
else if (indent == 1) indt = "\t";
else indt = "\t\t";
return fprintf(summary->fp, "%s</%s>\n", indt, tag);
}
int clar_summary_testsuites(struct clar_summary *summary)
{
return fprintf(summary->fp, "<testsuites>\n");
}
int clar_summary_testsuite(struct clar_summary *summary,
int idn, const char *name, const char *pkg, time_t timestamp,
double elapsed, int test_count, int fail_count, int error_count)
{
struct tm *tm = localtime(&timestamp);
char iso_dt[20];
if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0)
return -1;
return fprintf(summary->fp, "\t<testsuite "
" id=\"%d\""
" name=\"%s\""
" package=\"%s\""
" hostname=\"localhost\""
" timestamp=\"%s\""
" time=\"%.2f\""
" tests=\"%d\""
" failures=\"%d\""
" errors=\"%d\">\n",
idn, name, pkg, iso_dt, elapsed, test_count, fail_count, error_count);
}
int clar_summary_testcase(struct clar_summary *summary,
const char *name, const char *classname, double elapsed)
{
return fprintf(summary->fp,
"\t\t<testcase name=\"%s\" classname=\"%s\" time=\"%.2f\">\n",
name, classname, elapsed);
}
int clar_summary_failure(struct clar_summary *summary,
const char *type, const char *message, const char *desc)
{
return fprintf(summary->fp,
"\t\t\t<failure type=\"%s\"><![CDATA[%s\n%s]]></failure>\n",
type, message, desc);
}
struct clar_summary *clar_summary_init(const char *filename)
{
struct clar_summary *summary;
FILE *fp;
if ((fp = fopen(filename, "w")) == NULL)
return NULL;
if ((summary = malloc(sizeof(struct clar_summary))) == NULL) {
fclose(fp);
return NULL;
}
summary->filename = filename;
summary->fp = fp;
return summary;
}
int clar_summary_shutdown(struct clar_summary *summary)
{
struct clar_report *report;
const char *last_suite = NULL;
if (clar_summary_testsuites(summary) < 0)
goto on_error;
report = _clar.reports;
while (report != NULL) {
struct clar_error *error = report->errors;
if (last_suite == NULL || strcmp(last_suite, report->suite) != 0) {
if (clar_summary_testsuite(summary, 0, report->suite, "",
time(NULL), 0, _clar.tests_ran, _clar.total_errors, 0) < 0)
goto on_error;
}
last_suite = report->suite;
clar_summary_testcase(summary, report->test, "what", 0);
while (error != NULL) {
if (clar_summary_failure(summary, "assert",
error->error_msg, error->description) < 0)
goto on_error;
error = error->next;
}
if (clar_summary_close_tag(summary, "testcase", 2) < 0)
goto on_error;
report = report->next;
if (!report || strcmp(last_suite, report->suite) != 0) {
if (clar_summary_close_tag(summary, "testsuite", 1) < 0)
goto on_error;
}
}
if (clar_summary_close_tag(summary, "testsuites", 0) < 0 ||
fclose(summary->fp) != 0)
goto on_error;
printf("written summary file to %s\n", summary->filename);
free(summary);
return 0;
on_error:
fclose(summary->fp);
free(summary);
return -1;
}
#include "clar_libgit2.h"
static void assert_found(const char *haystack, const char *needle, size_t expected_pos)
{
cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
needle, needle ? strlen(needle) : 0),
haystack + expected_pos);
}
static void assert_absent(const char *haystack, const char *needle)
{
cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
needle, needle ? strlen(needle) : 0),
NULL);
}
void test_core_memmem__found(void)
{
assert_found("a", "a", 0);
assert_found("ab", "a", 0);
assert_found("ba", "a", 1);
assert_found("aa", "a", 0);
assert_found("aab", "aa", 0);
assert_found("baa", "aa", 1);
assert_found("dabc", "abc", 1);
assert_found("abababc", "abc", 4);
}
void test_core_memmem__absent(void)
{
assert_absent("a", "b");
assert_absent("a", "aa");
assert_absent("ba", "ab");
assert_absent("ba", "ab");
assert_absent("abc", "abcd");
assert_absent("abcabcabc", "bcac");
}
void test_core_memmem__edgecases(void)
{
assert_absent(NULL, NULL);
assert_absent("a", NULL);
assert_absent(NULL, "a");
assert_absent("", "a");
assert_absent("a", "");
}
#include "clar_libgit2.h"
void test_core_strtol__int32(void)
static void assert_l32_parses(const char *string, int32_t expected, int base)
{
int32_t i;
cl_git_pass(git__strntol32(&i, string, strlen(string), NULL, base));
cl_assert_equal_i(i, expected);
}
cl_git_pass(git__strtol32(&i, "123", NULL, 10));
cl_assert(i == 123);
cl_git_pass(git__strtol32(&i, " +123 ", NULL, 10));
cl_assert(i == 123);
cl_git_pass(git__strtol32(&i, " +2147483647 ", NULL, 10));
cl_assert(i == 2147483647);
cl_git_pass(git__strtol32(&i, " -2147483648 ", NULL, 10));
cl_assert(i == -2147483648LL);
static void assert_l32_fails(const char *string, int base)
{
int32_t i;
cl_git_fail(git__strntol32(&i, string, strlen(string), NULL, base));
}
cl_git_fail(git__strtol32(&i, " 2147483657 ", NULL, 10));
cl_git_fail(git__strtol32(&i, " -2147483657 ", NULL, 10));
static void assert_l64_parses(const char *string, int64_t expected, int base)
{
int64_t i;
cl_git_pass(git__strntol64(&i, string, strlen(string), NULL, base));
cl_assert_equal_i(i, expected);
}
void test_core_strtol__int64(void)
static void assert_l64_fails(const char *string, int base)
{
int64_t i;
cl_git_fail(git__strntol64(&i, string, strlen(string), NULL, base));
}
void test_core_strtol__int32(void)
{
assert_l32_parses("123", 123, 10);
assert_l32_parses(" +123 ", 123, 10);
assert_l32_parses(" +2147483647 ", 2147483647, 10);
assert_l32_parses(" -2147483648 ", -2147483648LL, 10);
assert_l32_parses("A", 10, 16);
assert_l32_parses("1x1", 1, 10);
cl_git_pass(git__strtol64(&i, "123", NULL, 10));
cl_assert(i == 123);
cl_git_pass(git__strtol64(&i, " +123 ", NULL, 10));
cl_assert(i == 123);
cl_git_pass(git__strtol64(&i, " +2147483647 ", NULL, 10));
cl_assert(i == 2147483647);
cl_git_pass(git__strtol64(&i, " -2147483648 ", NULL, 10));
cl_assert(i == -2147483648LL);
cl_git_pass(git__strtol64(&i, " 2147483657 ", NULL, 10));
cl_assert(i == 2147483657LL);
cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10));
cl_assert(i == -2147483657LL);
cl_git_pass(git__strtol64(&i, " 9223372036854775807 ", NULL, 10));
cl_assert(i == INT64_MAX);
cl_git_pass(git__strtol64(&i, " -9223372036854775808 ", NULL, 10));
cl_assert(i == INT64_MIN);
cl_git_pass(git__strtol64(&i, " 0x7fffffffffffffff ", NULL, 16));
cl_assert(i == INT64_MAX);
cl_git_pass(git__strtol64(&i, " -0x8000000000000000 ", NULL, 16));
cl_assert(i == INT64_MIN);
assert_l32_fails("", 10);
assert_l32_fails("a", 10);
assert_l32_fails("x10x", 10);
assert_l32_fails(" 2147483657 ", 10);
assert_l32_fails(" -2147483657 ", 10);
}
void test_core_strtol__int64(void)
{
assert_l64_parses("123", 123, 10);
assert_l64_parses(" +123 ", 123, 10);
assert_l64_parses(" +2147483647 ", 2147483647, 10);
assert_l64_parses(" -2147483648 ", -2147483648LL, 10);
assert_l64_parses(" 2147483657 ", 2147483657LL, 10);
assert_l64_parses(" -2147483657 ", -2147483657LL, 10);
assert_l64_parses(" 9223372036854775807 ", INT64_MAX, 10);
assert_l64_parses(" -9223372036854775808 ", INT64_MIN, 10);
assert_l64_parses(" 0x7fffffffffffffff ", INT64_MAX, 16);
assert_l64_parses(" -0x8000000000000000 ", INT64_MIN, 16);
assert_l64_parses("1a", 26, 16);
assert_l64_parses("1A", 26, 16);
assert_l64_fails("", 10);
assert_l64_fails("a", 10);
assert_l64_fails("x10x", 10);
assert_l64_fails("0x8000000000000000", 16);
assert_l64_fails("-0x8000000000000001", 16);
}
void test_core_strtol__buffer_length_truncates(void)
{
int32_t i32;
int64_t i64;
cl_git_pass(git__strntol32(&i32, "11", 1, NULL, 10));
cl_assert_equal_i(i32, 1);
cl_git_pass(git__strntol64(&i64, "11", 1, NULL, 10));
cl_assert_equal_i(i64, 1);
}
void test_core_strtol__error_message_cuts_off(void)
{
assert_l32_fails("2147483657foobar", 10);
cl_assert(strstr(giterr_last()->message, "2147483657") != NULL);
cl_assert(strstr(giterr_last()->message, "foobar") == NULL);
}
......@@ -263,6 +263,9 @@ static int cred_failure_cb(
void test_online_clone__cred_callback_failure_return_code_is_tunnelled(void)
{
git__free(_remote_url);
git__free(_remote_user);
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
_remote_user = git__strdup("libgit2test");
......@@ -293,6 +296,9 @@ void test_online_clone__cred_callback_called_again_on_auth_failure(void)
{
size_t counter = 0;
git__free(_remote_url);
git__free(_remote_user);
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
_remote_user = git__strdup("libgit2test");
......
......@@ -152,8 +152,12 @@ static void do_verify_push_status(record_callbacks_data *data, const push_status
git_buf_free(&msg);
}
git_vector_foreach(actual, i, iter)
git__free(iter);
git_vector_foreach(actual, i, iter) {
push_status *s = (push_status *)iter;
git__free(s->ref);
git__free(s->msg);
git__free(s);
}
git_vector_free(actual);
}
......@@ -393,7 +397,7 @@ void test_online_push__initialize(void)
}
git_remote_disconnect(_remote);
git_vector_free(&delete_specs);
git_vector_free_deep(&delete_specs);
/* Now that we've deleted everything, fetch from the remote */
memcpy(&fetch_opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment