Skip to content

Commit 0ac6212

Browse files
committed
Use gmtime_r() when available instead of gmtime()
Although gmtime_r() improves thread safety of date/time conversion because it is reentrant, it is only used by tr31-tool which is single threaded. This change is purely to make CodeQL happy.
1 parent d9fd51a commit 0ac6212

File tree

3 files changed

+50
-10
lines changed

3 files changed

+50
-10
lines changed

src/CMakeLists.txt

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ if(NOT argp_FOUND)
5050
endif()
5151

5252
# check for features required for date/time conversion:
53-
# locale.h, time.h, setlocale(), strptime(), timegm(), _mkgmtime(), and
54-
# localtime_r()
53+
# locale.h, time.h, setlocale(), strptime(), timegm(), _mkgmtime(),
54+
# localtime_r(), and gmtime_r()
5555
include(CheckIncludeFile)
5656
include(CheckSymbolExists)
5757
CHECK_INCLUDE_FILE(locale.h HAVE_LOCALE_H)
@@ -94,6 +94,17 @@ if(NOT HAVE_LOCALTIME_R)
9494
set(TIME_H_DEFINITIONS ${TIME_H_DEFINITIONS_TRY} CACHE INTERNAL "Definitions required for time.h")
9595
endif()
9696
endif()
97+
check_symbol_exists(gmtime_r time.h HAVE_GMTIME_R)
98+
if(NOT HAVE_GMTIME_R)
99+
unset(HAVE_GMTIME_R CACHE)
100+
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D${TIME_H_DEFINITIONS_TRY})
101+
check_symbol_exists(gmtime_r time.h HAVE_GMTIME_R)
102+
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D${TIME_H_DEFINITIONS_TRY})
103+
if(HAVE_GMTIME_R)
104+
# set as cache entry to persist across multiple builds
105+
set(TIME_H_DEFINITIONS ${TIME_H_DEFINITIONS_TRY} CACHE INTERNAL "Definitions required for time.h")
106+
endif()
107+
endif()
97108
# Only setlocale() and either timegm() or _mkgmtime() are required for
98109
# date/time conversion. If strptime() is absent, sscanf() will be used instead.
99110
if(HAVE_SETLOCALE AND (HAVE_TIMEGM OR HAVE_MKGMTIME))
@@ -166,6 +177,13 @@ install(
166177
# TR-31 command line tool
167178
if(BUILD_TR31_TOOL)
168179
add_executable(tr31-tool tr31-tool.c)
180+
if(HAVE_GMTIME_R AND TIME_H_DEFINITIONS)
181+
set_source_files_properties(tr31-tool.c
182+
PROPERTIES
183+
COMPILE_DEFINITIONS ${TIME_H_DEFINITIONS}
184+
)
185+
endif()
186+
target_include_directories(tr31-tool PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # for generated config file
169187
target_link_libraries(tr31-tool PRIVATE crypto_mem tr31)
170188
if(TARGET libargp::argp)
171189
target_link_libraries(tr31-tool PRIVATE libargp::argp)

src/tr31-tool.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020

2121
#include "tr31.h"
22+
#include "tr31_config.h"
2223
#include "tr31_strings.h"
2324

2425
#include "crypto_mem.h"
@@ -1361,20 +1362,30 @@ static int populate_opt_blocks(const struct tr31_tool_options_t* options, struct
13611362

13621363
if (strcmp(options->export_opt_block_TC_str, "now") == 0) {
13631364
time_t lt; // Calendar/Unix/POSIX time in local time
1364-
struct tm* ztm; // Time structure in UTC
1365+
struct tm ztm; // Time structure in UTC
1366+
struct tm* tm_ptr; // Result of gmtime functions
13651367
size_t ret;
13661368

13671369
lt = time(NULL);
13681370
if (lt == (time_t)-1) {
13691371
fprintf(stderr, "Failed to obtain current date/time: %s\n", strerror(errno));
13701372
return 1;
13711373
}
1372-
ztm = gmtime(&lt);
1373-
if (ztm == NULL) {
1374+
#ifdef HAVE_GMTIME_R
1375+
tm_ptr = gmtime_r(&lt, &ztm);
1376+
if (!tm_ptr) {
13741377
fprintf(stderr, "Failed to convert current date/time to UTC\n");
13751378
return 1;
13761379
}
1377-
ret = strftime(iso8601_now, sizeof(iso8601_now), "%Y%m%d%H%M%SZ", ztm);
1380+
#else
1381+
tm_ptr = gmtime(&lt);
1382+
if (!tm_ptr) {
1383+
fprintf(stderr, "Failed to convert current date/time to UTC\n");
1384+
return 1;
1385+
}
1386+
ztm = *tm_ptr;
1387+
#endif
1388+
ret = strftime(iso8601_now, sizeof(iso8601_now), "%Y%m%d%H%M%SZ", &ztm);
13781389
if (!ret) {
13791390
fprintf(stderr, "Failed to convert current date/time to ISO 8601\n");
13801391
return 1;
@@ -1396,20 +1407,30 @@ static int populate_opt_blocks(const struct tr31_tool_options_t* options, struct
13961407

13971408
if (strcmp(options->export_opt_block_TS_str, "now") == 0) {
13981409
time_t lt; // Calendar/Unix/POSIX time in local time
1399-
struct tm* ztm; // Time structure in UTC
1410+
struct tm ztm; // Time structure in UTC
1411+
struct tm* tm_ptr; // Result of gmtime functions
14001412
size_t ret;
14011413

14021414
lt = time(NULL);
14031415
if (lt == (time_t)-1) {
14041416
fprintf(stderr, "Failed to obtain current date/time: %s\n", strerror(errno));
14051417
return 1;
14061418
}
1407-
ztm = gmtime(&lt);
1408-
if (ztm == NULL) {
1419+
#ifdef HAVE_GMTIME_R
1420+
tm_ptr = gmtime_r(&lt, &ztm);
1421+
if (!tm_ptr) {
14091422
fprintf(stderr, "Failed to convert current date/time to UTC\n");
14101423
return 1;
14111424
}
1412-
ret = strftime(iso8601_now, sizeof(iso8601_now), "%Y%m%d%H%M%SZ", ztm);
1425+
#else
1426+
tm_ptr = gmtime(&lt);
1427+
if (!tm_ptr) {
1428+
fprintf(stderr, "Failed to convert current date/time to UTC\n");
1429+
return 1;
1430+
}
1431+
ztm = *tm_ptr;
1432+
#endif
1433+
ret = strftime(iso8601_now, sizeof(iso8601_now), "%Y%m%d%H%M%SZ", &ztm);
14131434
if (!ret) {
14141435
fprintf(stderr, "Failed to convert current date/time to ISO 8601\n");
14151436
return 1;

src/tr31_config.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#cmakedefine HAVE_TIMEGM
3434
#cmakedefine HAVE_MKGMTIME
3535
#cmakedefine HAVE_LOCALTIME_R
36+
#cmakedefine HAVE_GMTIME_R
3637
#cmakedefine TR31_ENABLE_DATETIME_CONVERSION
3738

3839
#endif

0 commit comments

Comments
 (0)