Skip to content

Commit

Permalink
fortify source against memory attacks (using ..._s-functions portably…
Browse files Browse the repository at this point in the history
…, or __builtin___..._chk-functions)
  • Loading branch information
jkriege2 committed May 8, 2024
1 parent d345766 commit 5b9bca7
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 131 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/build_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ jobs:
ls -R
- name: Build Debug
run: |
cmake --build build --config Release --verbose
cmake -G "${{matrix.gen}}" -DBUILD_SHARED_LIBS=${{matrix.shared}} "-DTinyTIFF_BUILD_TESTS=OFF" -DCMAKE_CXX_COMPILER=${{matrix.cxxcompiler}} -DCMAKE_C_COMPILER=${{matrix.ccompiler}} -DCMAKE_CXX_FLAGS_ALL_WARNINGS:STRING="-Wall" -DCMAKE_C_FLAGS_ALL_WARNINGS:STRING="-Wall" -B build_debug
cmake --build build_debug --config Debug --verbose
- name: Test CMake-build against TinyTIFF
run: |
cd tests
Expand Down
6 changes: 6 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ check_symbol_exists(fread_s "stdio.h" HAVE_FREAD_S)
check_symbol_exists(sprintf_s "stdio.h" HAVE_SPRINTF_S)
check_symbol_exists(strcat_s "string.h" HAVE_STRCAT_S)
check_symbol_exists(memcpy_s "string.h" HAVE_MEMCPY_S)
check_symbol_exists(memset_s "string.h" HAVE_MEMSET_S)
check_symbol_exists(strnlen_s "string.h" HAVE_STRNLEN_S)


Expand Down Expand Up @@ -88,6 +89,9 @@ endif()
if (HAVE_MEMCPY_S)
target_compile_definitions(${lib_name} PRIVATE HAVE_MEMCPY_S)
endif()
if (HAVE_MEMSET_S)
target_compile_definitions(${lib_name} PRIVATE HAVE_MEMSET_S)
endif()
if (HAVE_STRNLEN_S)
target_compile_definitions(${lib_name} PRIVATE HAVE_STRNLEN_S)
endif()
Expand All @@ -108,6 +112,7 @@ set_property(SOURCE tinytiffreader.c tinytiffreader.h PROPERTY LANGUAGE "C")
set_property(SOURCE tinytiffwriter.c tinytiffwriter.h PROPERTY LANGUAGE "C")
set_property(SOURCE tiff_definitions_internal.h tinytiff_defs.h PROPERTY LANGUAGE "C")
target_sources(${lib_name} PRIVATE
tinytiff_ctools_internal.c
tinytiffreader.c
tinytiffwriter.c
)
Expand All @@ -116,6 +121,7 @@ target_sources(${lib_name} PRIVATE
target_sources(${lib_name} PRIVATE FILE_SET privateHEADERS TYPE HEADERS
FILES
tiff_definitions_internal.h
tinytiff_ctools_internal.h
)

target_sources(${lib_name} PUBLIC FILE_SET HEADERS TYPE HEADERS
Expand Down
16 changes: 4 additions & 12 deletions src/tiff_definitions_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef TIFF_DEFINITIONS_INTERNAL_H
#define TIFF_DEFINITIONS_INTERNAL_H

Expand Down Expand Up @@ -94,16 +98,4 @@



#ifdef HAVE_STRCPY_S
#define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message);
#else
#define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy(tiff->lastError, message);
#endif

#ifdef HAVE_SPRINTF_S
#define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message, __VA_ARGS__);
#else
#define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf(tiff->lastError, message, __VA_ARGS__);
#endif

#endif // TIFF_DEFINITIONS_INTERNAL_H
81 changes: 81 additions & 0 deletions src/tinytiff_ctools_internal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
Copyright (c) 2008-2024 Jan W. Krieger (<[email protected]>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tinytiff_ctools_internal.h"
#include <string.h>
#include <assert.h>

#ifdef __has_builtin

# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin (__builtin___memcpy_chk)
# define tinytiff_builtin_memcpy_chk(dest, src, n) __builtin___memcpy_chk(dest, src, n, tinytiff_builtin_object_size0(dest))
# endif

# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin (__builtin___memset_chk)
# define tinytiff_builtin_memset_chk(dest, ch, n) __builtin___memset_chk(dest, ch, n, tinytiff_builtin_object_size0(dest))
# endif

#endif

void TinyTIFF_memcpy_s(void *dest, unsigned long destsz, const void *src, unsigned long count) {
if (count<=0) return;
#ifdef HAVE_MEMCPY_S
memcpy_s(dest, destsz, src, count);
#else
# if defined(tinytiff_builtin_memcpy_chk)
tinytiff_builtin_memcpy_chk(dest, src, count);
# else
assert((dest!=NULL) && "TinyTIFF_memcpy_s: dest==NULL");
assert((src!=NULL) && "TinyTIFF_memcpy_s: src==NULL");
#if defined(TINYTIFF_HASOBJSIZE)
assert((tinytiff_builtin_object_size(dest,1)>=destsz) && "TinyTIFF_memcpy_s: dest too small (destsz incorrect)");
assert((tinytiff_builtin_object_size(dest,1)>=count) && "TinyTIFF_memcpy_s: dest too small (count larger than available memory)");
assert((tinytiff_builtin_object_size(src,1)>=count) && "TinyTIFF_memcpy_s: src too small");
#endif
memcpy(dest, src, count);
# endif
#endif
}

void TinyTIFF_memset_s(void *dest, unsigned long destsz, char ch, unsigned long count)
{
#ifdef HAVE_MEMSET_S
memset_s(dest, destsz, ch, count);
#else
# if defined(tinytiff_builtin_memset_chk)
tinytiff_builtin_memset_chk(dest, ch, count);
# else
memset(dest, ch, count);
# endif
#endif

}

unsigned long TinyTIFF_strlen_s(const char *str, unsigned long strsz)
{
#ifdef HAVE_STRLEN_S
return strlen_s(str, strsz);
#else
if (str==NULL) return 0;
#if defined(TINYTIFF_HASOBJSIZE)
assert((tinytiff_builtin_object_size1(str)>=strsz) && "TinyTIFF_strlen_s: str too small (strsz incorrect)");
#endif
return strlen(str);
#endif

}
90 changes: 90 additions & 0 deletions src/tinytiff_ctools_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
Copyright (c) 2008-2024 Jan W. Krieger (<[email protected]>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef TINYTIFF_CTOOLS_INTERNAL_H
#define TINYTIFF_CTOOLS_INTERNAL_H

#if defined(__has_builtin)
# if __has_builtin(__builtin_object_size)
# define tinytiff_builtin_object_size(ptr) __builtin_object_size(ptr, 2)
# define tinytiff_builtin_object_size0(dest) __builtin_object_size (dest, 0)
# define tinytiff_builtin_object_size1(dest) __builtin_object_size (dest, 1)
# define TINYTIFF_HASOBJSIZE
# endif
#endif

#ifdef HAVE_STRCPY_S
#define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message);
#define TINYTIFF_STRCPY_S(dest, dsize, src) strcpy_s(dest, dsize, src);
#else
# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin(__builtin___strcpy_chk)
# define TINYTIFF_SET_LAST_ERROR(tiff, message) __builtin___strcpy_chk(tiff->lastError, message, tinytiff_builtin_object_size0(tiff->lastError))
# define TINYTIFF_STRCPY_S(dest, dsize, src) __builtin___strcpy_chk(dest, src, tinytiff_builtin_object_size0(dest))
# else
# define TINYTIFF_SET_LAST_ERROR(tiff, message) strcpy(tiff->lastError, message);
# define TINYTIFF_STRCPY_S(dest, dsize, src) strcpy(dest, src);
# endif
#endif


#ifdef HAVE_STRCAT_S
#define TINYTIFF_STRCAT_S(dest, dsize, src) strcat_s(dest, dsize, src);
#else
# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin(__builtin___strcat_chk)
# define TINYTIFF_STRCAT_S(dest, dsize, src) __builtin___strcat_chk(dest, src, tinytiff_builtin_object_size0(dest))
# else
# define TINYTIFF_STRCAT_S(dest, dsize, src) strcat(dest, src);
# endif
#endif


#ifdef HAVE_SPRINTF_S
# define TINYTIFF_SPRINTF_S(str, ssize, message, ...) sprintf_s(str, ssize, message, __VA_ARGS__);
# define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf_s(tiff->lastError, TIFF_LAST_ERROR_SIZE, message, __VA_ARGS__);
#else
# if defined(TINYTIFF_HASOBJSIZE) && __has_builtin(__builtin___sprintf_chk)
# define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) __builtin___sprintf_chk(tiff->lastError, 0, tinytiff_builtin_object_size0(tiff->lastError), message, __VA_ARGS__)
# define TINYTIFF_SPRINTF_S(str, ssize, message, ...) __builtin___sprintf_chk(str, 0, tinytiff_builtin_object_size0(str), message, __VA_ARGS__)
# else
# define TINYTIFF_SPRINTF_S(str, ssize, message, ...) sprintf(str, message, __VA_ARGS__);
# define TINYTIFF_SPRINTF_LAST_ERROR(tiff, message, ...) sprintf(tiff->lastError, message, __VA_ARGS__);
# endif
#endif


/** \brief hardened memcpy(), that calls memcpy_s() or __builtin___memcpy_chk() if available
* \internal
* \ingroup tinytiffreader_internal
*/
void TinyTIFF_memcpy_s( void * dest, unsigned long destsz, const void * src, unsigned long count );

/** \brief hardened memset(), that calls memset_s() or __builtin___memset_chk() if available
* \internal
* \ingroup tinytiffreader_internal
*/
void TinyTIFF_memset_s( void * dest, unsigned long destsz, char ch, unsigned long count );

/** \brief hardened strlen(), that calls strlen_s() or __builtin___strlen_chk() if available
* \internal
* \ingroup tinytiffreader_internal
*/
unsigned long TinyTIFF_strlen_s( const char * str, unsigned long strsz);

#endif // TINYTIFF_CTOOLS_INTERNAL_H
18 changes: 7 additions & 11 deletions src/tinytiffreader.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@
*/
#include "tinytiffreader.h"
#include "tiff_definitions_internal.h"
#include "tinytiff_ctools_internal.h"
#include "tinytiff_version.h"
//#define DEBUG_IFDTIMING
#ifdef DEBUG_IFDTIMING
#include "highrestimer.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

Expand Down Expand Up @@ -189,14 +193,6 @@ unsigned long TinyTIFFReader_doRangesOverlap(unsigned long xstart, unsigned long
return TINYTIFF_FALSE;
}

int TinyTIFFReader_memcpy_s( void * dest, unsigned long destsz, const void * src, unsigned long count ) {
#ifdef HAVE_MEMCPY_S
return memcpy_s(dest, destsz, src, count);
#else
memcpy(dest, src, count);
return 0;
#endif
}

void TinyTIFFReader_fopen(TinyTIFFReaderFile* tiff, const char* filename) {
#ifdef TINYTIFF_USE_WINAPI_FOR_FILEIO
Expand Down Expand Up @@ -618,7 +614,7 @@ static void TinyTIFFReader_readNextFrame(TinyTIFFReaderFile* tiff) {
tiff->currentFrame.stripcount=ifd.count;
tiff->currentFrame.stripoffsets=(uint32_t*)calloc(ifd.count, sizeof(uint32_t));
if (tiff->currentFrame.stripoffsets) {
TinyTIFFReader_memcpy_s(tiff->currentFrame.stripoffsets, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t));
TinyTIFF_memcpy_s(tiff->currentFrame.stripoffsets, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t));
} else {
tiff->wasError=TINYTIFF_TRUE;
TINYTIFF_SET_LAST_ERROR(tiff, "unable to allocate memory\0");
Expand Down Expand Up @@ -652,7 +648,7 @@ static void TinyTIFFReader_readNextFrame(TinyTIFFReaderFile* tiff) {
if (ifd.count>0 && ifd.pvalue) {
tiff->currentFrame.stripcount=ifd.count;
tiff->currentFrame.stripbytecounts=(uint32_t*)calloc(ifd.count, sizeof(uint32_t));
TinyTIFFReader_memcpy_s(tiff->currentFrame.stripbytecounts, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t));
TinyTIFF_memcpy_s(tiff->currentFrame.stripbytecounts, ifd.count*sizeof(uint32_t), ifd.pvalue, ifd.count*sizeof(uint32_t));
} else {
tiff->wasError=TINYTIFF_TRUE;
TINYTIFF_SET_LAST_ERROR(tiff, "STRIPBYTECOUNTS has an invalid value (==0) or error reading data!\0");
Expand Down Expand Up @@ -851,7 +847,7 @@ int TinyTIFFReader_getSampleData_s___internl(TinyTIFFReaderFile* tiff, void* buf
}
unsigned long stripi=0;
for (stripi=sample*tiff->currentFrame.bitspersample/8; stripi<stripsize_bytes; stripi+=tiff->currentFrame.bitspersample/8*tiff->currentFrame.samplesperpixel) {
if (doSizeChecks) TinyTIFFReader_memcpy_s(&(((uint8_t*)buffer)[outputimageidx_bytes]), buffer_size-outputimageidx_bytes, &(stripdata[stripi]), tiff->currentFrame.bitspersample/8);
if (doSizeChecks) TinyTIFF_memcpy_s(&(((uint8_t*)buffer)[outputimageidx_bytes]), buffer_size-outputimageidx_bytes, &(stripdata[stripi]), tiff->currentFrame.bitspersample/8);
else memcpy(&(((uint8_t*)buffer)[outputimageidx_bytes]), &(stripdata[stripi]), tiff->currentFrame.bitspersample/8);
#ifdef TINYTIFF_ADDITIONAL_DEBUG_MESSAGES
if (stripi<sample*tiff->currentFrame.bitspersample/8+10*tiff->currentFrame.bitspersample/8*tiff->currentFrame.samplesperpixel) printf(" - memcpy(buffer[%8lu], stripdata[%8lu], %lu)\n", (unsigned long)outputimageidx_bytes, (unsigned long)stripi, (unsigned long)(tiff->currentFrame.bitspersample/8));
Expand Down
5 changes: 1 addition & 4 deletions src/tinytiffreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@

#include "tinytiff_export.h"
#include "tinytiff_defs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <stdint.h>


/*! \defgroup tinytiffreader Tiny TIFF reader library
Expand Down
Loading

0 comments on commit 5b9bca7

Please sign in to comment.