Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ cert-STR52
cert-STR53
compile_commands.json
dynamic_pointer_cast
lookAndSay
safeComparison
slice
slide
strcat
strcat_s
timeConversion
to_string
lookAndSay
23 changes: 16 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
cmake_minimum_required(VERSION 3.15...3.19)
cmake_minimum_required(VERSION 3.14...3.30)

option(CMAKE_EXPORT_COMPILE_COMMANDS "create compile_commands.json" ON)

project(cert-test LANGUAGES CXX VERSION 0.1.8)
project(cert-test LANGUAGES CXX C VERSION 0.1.9)

#----------------------------------------------------------
# Compiler config
#----------------------------------------------------------
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
Expand All @@ -28,12 +28,16 @@ find_program(CLANG_TIDY
if(CLANG_TIDY)
if(ENABLE_CLANG_TIDY)
message(STATUS "set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY})")
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_CMD} CACHE STRING "forced!" FORCE)
set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY} CACHE STRING "forced!" FORCE)
else()
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "forced!" FORCE) # delete it
endif()
endif()

add_library(rary STATIC library.cpp library.h)
target_include_directories(rary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_features(rary PRIVATE cxx_std_98)

#----------------------------------------------------------
enable_testing()
#----------------------------------------------------------
Expand All @@ -47,7 +51,7 @@ foreach(TEST_SOURCE ${TESTS})

add_executable(${TEST_TARGET} ${TEST_SOURCE})
target_compile_features(${TEST_TARGET} PRIVATE cxx_std_17)
target_link_libraries(${TEST_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library.a)
target_link_libraries(${TEST_TARGET} PRIVATE rary)
add_test(NAME "${TEST_TARGET}" COMMAND "${TEST_TARGET}")

endforeach()
Expand Down Expand Up @@ -98,8 +102,9 @@ find_package(Boost CONFIG)


if(TARGET Boost::headers AND TARGET fmt::fmt)
add_executable(to_string to_string.cpp)
target_link_libraries(to_string fmt::fmt Boost::headers)
#FIXME! CK
#XXX add_executable(to_string to_string.cpp)
#XXX target_link_libraries(to_string fmt::fmt Boost::headers)
endif()


Expand All @@ -114,6 +119,10 @@ target_compile_features(dynamic_pointer_cast PRIVATE cxx_std_17)
add_executable(slice slice.cpp)
target_compile_features(slice PRIVATE cxx_std_17)

add_executable(strcat_s strcat_s.c)
target_compile_features(strcat_s PRIVATE cxx_std_17)
add_test(NAME strcat_s COMMAND strcat_s)

add_executable(lookAndSay lookAndSay.cpp)
target_compile_features(lookAndSay PRIVATE cxx_std_17)

Expand Down
82 changes: 82 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"version": 9,
"configurePresets": [
{
"name": "default",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "${presetName}"
},
"environment": {
"PRESET_NAME": "${presetName}"
}
},
{
"name": "Debug",
"inherits": "default"
},
{
"name": "Release",
"inherits": "default"
}
],
"buildPresets": [
{
"name": "Debug",
"configurePreset": "Debug"
},
{
"name": "Release",
"configurePreset": "Release"
}
],
"testPresets": [
{
"name": "Debug",
"configurePreset": "Debug"
},
{
"name": "Release",
"configurePreset": "Release"
}

],
"workflowPresets": [
{
"name": "Debug",
"steps": [
{
"type": "configure",
"name": "Debug"
},
{
"type": "build",
"name": "Debug"
},
{
"type": "test",
"name": "Debug"
}
]
},
{
"name": "Release",
"steps": [
{
"type": "configure",
"name": "Release"
},
{
"type": "build",
"name": "Release"
},
{
"type": "test",
"name": "Release"
}
]
}
]
}
15 changes: 8 additions & 7 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ GENERATOR?=-G Ninja
TARGET_ARCH:=
CPPFLAGS?=-isystem /usr/local/include

#XXX CC:=gcc-10
#XXX CC:=gcc-14
CC:=clang
CFLAGS:=-std=c11 -Wextra -Wpedantic -Wshadow
CFLAGS:=-std=c17 -Wextra -Wpedantic -Wshadow

#XXX CXX:=g++-10
#XXX CXX:=g++-14
CXX:=clang++
CXXFLAGS:=-std=c++17 -Wextra -Wpedantic -Wshadow
CXXFLAGS:=-std=c++17 -Wextra -Wpedantic -Wshadow -Warray-bounds

LDLIBS:=$(CURDIR)/library.a
LDFLAGS:=-L/usr/local/lib
Expand All @@ -41,15 +41,15 @@ BUILDDIR?=$(CURDIR)/build
UNAME:=$(shell uname)
ifeq ($(UNAME),Darwin)
SCAN_BUILD?=/usr/local/opt/llvm/bin/scan-build
#XXX CPPFLAGS+=-isystem /usr/local/Cellar/llvm/11.0.0/include/c++/v1/
#XXX CPPFLAGS+=-isystem /usr/local/Cellar/llvm/19.1.0/include/c++/v1/
else
CLANG_VERSION:=$(shell clang --version | grep -w version | perl -n -e 'print if s/^.*clang version (\d+)\..*/$$1/')
SCAN_BUILD:=$(shell which scan-build-$(CLANG_VERSION) || which scan-build)
endif


#
# from https://wiki.sei.cmu.edu/confluence/display/cplusplus/Clang
#XXX # from https://wiki.sei.cmu.edu/confluence/display/cplusplus/Clang
#
#XXX CXXFLAGS+=-analyzer-checker=cplusplus # EXP51-CPP. Do not delete an array through a pointer of the incorrect type

Expand Down Expand Up @@ -89,7 +89,8 @@ export CC
.PHONY: init all build check test format clean distclean

TESTS:=$(wildcard cert-*.cpp)
#XXX TESTS+=cereal-test.cpp dynamic_pointer_cast.cpp safeComparison.cpp slice.cpp slide.cpp timeConversion.cpp to_string.cpp
#XXX TESTS+= strcat.cpp
#XXX TESTS+= cereal-test.cpp dynamic_pointer_cast.cpp safeComparison.cpp slice.cpp slide.cpp timeConversion.cpp to_string.cpp
PROGRAMS:=$(TESTS:%.cpp=%)

######################################
Expand Down
2 changes: 1 addition & 1 deletion cert-CTR58.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace {

class MutablePredicate : public std::unary_function<int, bool>
class MutablePredicate : public std::__unary_function<int, bool>
{
size_t timesCalled;

Expand Down
110 changes: 110 additions & 0 deletions strcat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Abstract
//
// The standard C library includes functions that are designed to prevent
// buffer overflows, particularly strncpy() and strncat(). These
// universally available functions discard data larger than the specified
// length, regardless of whether it fits into the buffer. These functions
// are deprecated for new Windows code because they are frequently used
// incorrectly.
//
// see too
// https://us-cert.cisa.gov/bsi/articles/knowledge/coding-practices/strncpy-and-strncat
// https://us-cert.cisa.gov/bsi/articles/knowledge/coding-practices/strlcpy-and-strlcat
// and
// https://us-cert.cisa.gov/bsi/articles/knowledge/coding-practices/strcpy_s-and-strcat_s
//
#include <cassert>
#include <cstring>
#include <iostream>

constexpr size_t MAXPATHLEN{256};
constexpr size_t MAX_STRING_LEN{50};
constexpr const char* source = {"A not too long sentence here! "};
constexpr const char* more = {"Too mutch ... text!!!!!"};
const char *dir = "/usr/local/etc/snmp/";
const char *file = "snmpd.conf";

namespace {

#if !(defined(__APPLE__) || defined(__BSD__))
// If the return value is >= dstsize, the output string has been
// truncated. It is the caller's responsibility to handle this
size_t strlcpy(char* dst, const char* src, size_t len)
{
int n = snprintf(dst, len, "%s", src);
assert(n >= 0 && (size_t)n < len);

return n;
}
#endif

void good_sample()
{
char pname[MAXPATHLEN];
size_t capacity = sizeof(pname);

// ...

size_t n = strlcpy(pname, dir, capacity);
if (n >= capacity)
{
goto toolong;
}

capacity = sizeof(pname) - n ;
if (strlcpy(pname + n, file, capacity ) >= capacity)
{
goto toolong;
}

std::cout << pname << std::endl;
return;

toolong:
std::cerr << "truncated pname!" << std::endl;
exit(EXIT_FAILURE);
}

} // namespace local

int main()
{
good_sample();

char dest[MAX_STRING_LEN + 1];

#undef USE_STRNCPY
#ifndef USE_STRNCPY
strlcpy(dest, source, MAX_STRING_LEN);
#else
// The strncpy() function doesn't null terminate the destination
// string if the source string is at least as long as the
// destination. (This behavior is defined by the C99 specification.)
// As a result, the destination string MUST be null terminated after
// calling strncpy().
strncpy(dest, source, MAX_STRING_LEN);
dest[MAX_STRING_LEN] = '\0'; // NOTE: to be sure! CK

// There's also a performance problem with strncpy() in that it fills
// the entire destination buffer with null bytes after the source
// data has been exhausted!
#endif

std::cout << dest << std::endl;

#undef SHOW_THE_BUG
#ifdef SHOW_THE_BUG
strncat(dest, source, MAX_STRING_LEN); // FIXME: buffer overflow!
std::cout << dest << std::endl;
dest[MAX_STRING_LEN] = '\0';
#endif

// The problem is that the last argument to strncat() should NOT be
// the total buffer length! It should be the space remaining after
// the call to strncpy(). Both functions require that you specify the
// remaining space and not the total size of the buffer.
strncat(dest, more, sizeof(dest) - strlen(dest) - 1);

assert(strlen(dest) == MAX_STRING_LEN);
std::cout << dest << std::endl;
}
Loading
Loading