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
11 changes: 5 additions & 6 deletions cfg/std.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3238,16 +3238,15 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<not-uninit/>
</arg>
</function>
<!-- struct tm *localtime_s(const time_t *restrict time, struct tm *restrict result) -->
<function name="localtime_s,std::localtime_s">
<returnValue type="struct tm *"/>
<!-- struct tm *localtime_s(const time_t *restrict time, struct tm *restrict result)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently gmtime_s() has the same issue, see https://trac.cppcheck.net/ticket/11826

Order of arguments and return type differs between implementations, define a common baseline here. -->
<function name="localtime_s">
<noreturn>false</noreturn>
<leak-ignore/>
<arg nr="1" direction="in">
<arg nr="1">
<not-null/>
<not-uninit/>
</arg>
<arg nr="2" direction="out">
<arg nr="2">
<not-null/>
</arg>
</function>
Expand Down
5 changes: 3 additions & 2 deletions cfg/windows.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4654,9 +4654,10 @@ HFONT CreateFont(
<not-uninit/>
</arg>
</function>
<!-- errno_t _localtime32_s( struct tm* _tm, const __time32_t *time);
<!-- errno_t localtime_s( struct tm* const tmDest, time_t const* const sourceTime);
errno_t _localtime32_s( struct tm* _tm, const __time32_t *time);
errno_t _localtime64_s( struct tm* _tm, const __time64_t *time); -->
<function name="_localtime32_s,_localtime64_s">
<function name="localtime_s,_localtime32_s,_localtime64_s">
<returnValue type="errno_t"/>
<noreturn>false</noreturn>
<leak-ignore/>
Expand Down
20 changes: 0 additions & 20 deletions test/cfg/std.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,26 +171,6 @@ void nullPointer_qsort(void *base, size_t n, size_t size, int (*cmp)(const void
qsort(base, n, size, qsort_cmpfunc);
}

// As with all bounds-checked functions, localtime_s is only guaranteed to be available if __STDC_LIB_EXT1__ is defined by the implementation and if the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1 before including time.h.
#ifdef __STDC_LIB_EXT1__
void uninitvar_localtime_s(const time_t *restrict time, struct tm *restrict result)
{
const time_t *restrict Time;
// cppcheck-suppress uninitvar
(void)localtime_s(Time, result);
(void)localtime_s(time, result);
}

void nullPointer_localtime_s(const time_t *restrict time, struct tm *restrict result)
{
// cppcheck-suppress nullPointer
(void)localtime_s(NULL, result);
// cppcheck-suppress nullPointer
(void)localtime_s(time, NULL);
(void)localtime_s(time, result);
}
#endif // __STDC_LIB_EXT1__

size_t bufferAccessOutOfBounds_wcsrtombs(char * dest, const wchar_t ** src, size_t len, mbstate_t * ps)
{
char buf[42];
Expand Down
32 changes: 0 additions & 32 deletions test/cfg/std.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,38 +689,6 @@ void *bufferAccessOutOfBounds_memchr(void *s, int c, size_t n)
return std::memchr(s,c,n);
}

// As with all bounds-checked functions, localtime_s is only guaranteed to be available if __STDC_LIB_EXT1__ is defined by the implementation and if the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1 before including time.h.
#ifdef __STDC_LIB_EXT1__
void uninitvar_localtime_s(const std::time_t *restrict time, struct tm *restrict result)
{
// cppcheck-suppress valueFlowBailoutIncompleteVar
const std::time_t *restrict Time;
// TODO cppcheck-suppress uninitvar
(void)std::localtime_s(Time, result);
(void)std::localtime_s(time, result);
}

void nullPointer_localtime_s(const std::time_t *restrict time, struct tm *restrict result)
{
// cppcheck-suppress nullPointer
(void)std::localtime_s(NULL, result);
// cppcheck-suppress nullPointer
(void)std::localtime_s(time, NULL);
(void)std::localtime_s(time, result);
}

void memleak_localtime_s(const std::time_t *restrict time, struct tm *restrict result) // #9258
{
const time_t t = time(0);
const struct tm* const now = new tm();
if (localtime_s(now, &t) == 0) {
// cppcheck-suppress valueFlowBailoutIncompleteVar
std::cout << now->tm_mday << std::endl;
}
// cppcheck-suppress memleak
}
#endif // __STDC_LIB_EXT1__

size_t nullPointer_strftime(char *s, size_t max, const char *fmt, const struct tm *p)
{
// cppcheck-suppress nullPointer
Expand Down
28 changes: 28 additions & 0 deletions test/cfg/windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1260,3 +1260,31 @@ void constParameterPointer_SetupDiGetDeviceInstanceId(HDEVINFO info, SP_DEVINFO_
TCHAR buffer[buffer_size];
SetupDiGetDeviceInstanceId(info, data, buffer, buffer_size, NULL);
}

void uninitvar_localtime_s(const time_t *time, struct tm *result)
{
time_t uninit_time;
struct tm uninit_result;
// cppcheck-suppress uninitvar
(void)localtime_s(result, &uninit_time);
(void)localtime_s(&uninit_result, time);
(void)localtime_s(result, time);
}

void nullPointer_localtime_s(const time_t *time, struct tm *result)
{
// cppcheck-suppress nullPointer
(void)localtime_s(result, NULL);
// cppcheck-suppress nullPointer
(void)localtime_s(NULL, time);
(void)localtime_s(result, time);
}

void memleak_localtime_s(void) // #9258
{
const time_t t = time(0);
struct tm *const now = new tm();
if (localtime_s(now, &t) == 0)
printf("%d\n", now->tm_mday);
// cppcheck-suppress memleak
}
Loading