Skip to content

Commit cc7a041

Browse files
committed
Additional tweaks for Windows (buffer size issues)
1 parent 695a9a8 commit cc7a041

File tree

2 files changed

+46
-35
lines changed

2 files changed

+46
-35
lines changed

Release/src/utilities/asyncrt_utils.cpp

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ using namespace Platform;
3030
using namespace Windows::Storage::Streams;
3131
#endif // #if !defined(__cplusplus_winrt)
3232

33-
#if !defined(_MS_WINDOWS)
33+
#if defined(_MS_WINDOWS)
34+
#include <regex>
35+
#else
3436
#include <boost/date_time/posix_time/posix_time.hpp>
3537
#include <boost/date_time/posix_time/posix_time_io.hpp>
3638
// GCC 4.8 does not support regex, use boost. TODO: switch to std::regex in GCC 4.9
@@ -554,24 +556,25 @@ utility::string_t datetime::to_string(date_format format) const
554556
}
555557
else if ( format == ISO_8601 )
556558
{
559+
const size_t buffSize = 64;
557560
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
558-
TCHAR dateStr[18] = {0};
559-
status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, "yyyy-MM-dd", dateStr, sizeof(dateStr) / sizeof(wchar_t));
561+
TCHAR dateStr[buffSize] = {0};
562+
status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, "yyyy-MM-dd", dateStr, buffSize);
560563
#else
561-
wchar_t dateStr[18] = {0};
562-
status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, sizeof(dateStr) / sizeof(wchar_t), NULL);
564+
wchar_t dateStr[buffSize] = {0};
565+
status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize, NULL);
563566
#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
564567
if (status == 0)
565568
{
566569
throw utility::details::create_system_error(GetLastError());
567570
}
568571

569572
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
570-
TCHAR timeStr[10] = {0};
571-
status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, "HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t));
573+
TCHAR timeStr[buffSize] = {0};
574+
status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, "HH':'mm':'ss", timeStr, buffSize);
572575
#else
573-
wchar_t timeStr[10] = {0};
574-
status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t));
576+
wchar_t timeStr[buffSize] = {0};
577+
status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize);
575578
#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
576579
if (status == 0)
577580
{
@@ -632,7 +635,7 @@ utility::string_t datetime::to_string(date_format format) const
632635
}
633636

634637
#ifdef _MS_WINDOWS
635-
bool __cdecl datetime::system_type_to_datetime(void* pvsysTime, double seconds, datetime * pdt)
638+
bool __cdecl datetime::system_type_to_datetime(void* pvsysTime, uint64_t seconds, datetime * pdt)
636639
{
637640
SYSTEMTIME* psysTime = (SYSTEMTIME*)pvsysTime;
638641
FILETIME fileTime;
@@ -644,8 +647,7 @@ bool __cdecl datetime::system_type_to_datetime(void* pvsysTime, double seconds,
644647
largeInt.HighPart = fileTime.dwHighDateTime;
645648

646649
// Add hundredths of nanoseconds
647-
uint64_t hn = (uint64_t)(seconds * _secondTicks);
648-
largeInt.QuadPart += hn;
650+
largeInt.QuadPart += seconds;
649651

650652
*pdt = datetime(largeInt.QuadPart);
651653
return true;
@@ -676,6 +678,9 @@ uint64_t timeticks_from_second(const utility::string_t& str)
676678
/// </summary>
677679
datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format)
678680
{
681+
// avoid floating point math to preserve precision
682+
uint64_t ufrac_second = 0;
683+
679684
#ifdef _MS_WINDOWS
680685
datetime result;
681686
if ( format == RFC_1123 )
@@ -704,7 +709,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
704709
if (loc != monthnames+12)
705710
{
706711
sysTime.wMonth = (short) ((loc - monthnames) + 1);
707-
if (system_type_to_datetime(&sysTime, 0.0, &result))
712+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
708713
{
709714
return result;
710715
}
@@ -715,23 +720,33 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
715720
{
716721
// Unlike FILETIME, SYSTEMTIME does not have enough precision to hold seconds in 100 nanosecond
717722
// increments. Therefore, start with seconds and milliseconds set to 0, then add them separately
718-
// from this double:
719-
double seconds;
723+
724+
// Try to extract the fractional second from the timestamp
725+
std::wregex r_frac_second(L"(.+)(\\.\\d+)(Z$)");
726+
std::wsmatch m;
727+
728+
std::wstring input(dateString);
729+
if (std::regex_search(dateString, m, r_frac_second))
730+
{
731+
auto frac = m[2].str(); // this is the fractional second
732+
ufrac_second = timeticks_from_second(frac);
733+
input = m[1].str() + m[3].str();
734+
}
720735

721736
{
722737
SYSTEMTIME sysTime = { 0 };
723-
const wchar_t * formatString = L"%4d-%2d-%2dT%2d:%2d:%lfZ";
724-
auto n = swscanf_s(dateString.c_str(), formatString,
738+
const wchar_t * formatString = L"%4d-%2d-%2dT%2d:%2d:%2dZ";
739+
auto n = swscanf_s(input.c_str(), formatString,
725740
&sysTime.wYear,
726741
&sysTime.wMonth,
727742
&sysTime.wDay,
728743
&sysTime.wHour,
729744
&sysTime.wMinute,
730-
&seconds);
745+
&sysTime.wSecond);
731746

732747
if (n == 3 || n == 6)
733748
{
734-
if (system_type_to_datetime(&sysTime, seconds, &result))
749+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
735750
{
736751
return result;
737752
}
@@ -741,12 +756,12 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
741756
SYSTEMTIME sysTime = {0};
742757
DWORD date = 0;
743758

744-
const wchar_t * formatString = L"%8dT%2d:%2d:%lfZ";
745-
auto n = swscanf_s(dateString.c_str(), formatString,
759+
const wchar_t * formatString = L"%8dT%2d:%2d:%2dZ";
760+
auto n = swscanf_s(input.c_str(), formatString,
746761
&date,
747762
&sysTime.wHour,
748763
&sysTime.wMinute,
749-
&seconds);
764+
&sysTime.wSecond);
750765

751766
if (n == 1 || n == 4)
752767
{
@@ -756,7 +771,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
756771
date /= 100;
757772
sysTime.wYear = (WORD)date;
758773

759-
if (system_type_to_datetime(&sysTime, seconds, &result))
774+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
760775
{
761776
return result;
762777
}
@@ -765,19 +780,18 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
765780
{
766781
SYSTEMTIME sysTime = {0};
767782
GetSystemTime(&sysTime); // Fill date portion with today's information
768-
// Zero out second -- we will use the double for that
769783
sysTime.wSecond = 0;
770784
sysTime.wMilliseconds = 0;
771785

772-
const wchar_t * formatString = L"%2d:%2d:%lfZ";
773-
auto n = swscanf_s(dateString.c_str(), formatString,
786+
const wchar_t * formatString = L"%2d:%2d:%2dZ";
787+
auto n = swscanf_s(input.c_str(), formatString,
774788
&sysTime.wHour,
775789
&sysTime.wMinute,
776-
&seconds);
790+
&sysTime.wSecond);
777791

778792
if (n == 3)
779793
{
780-
if (system_type_to_datetime(&sysTime, seconds, &result))
794+
if (system_type_to_datetime(&sysTime, ufrac_second, &result))
781795
{
782796
return result;
783797
}
@@ -791,9 +805,6 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
791805

792806
struct tm output = tm();
793807

794-
// avoid floating point math to preserve precision
795-
uint64_t ufrac_second = 0;
796-
797808
if ( format == RFC_1123 )
798809
{
799810
strptime(input.data(), "%a, %d %b %Y %H:%M:%S GMT", &output);
@@ -810,7 +821,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
810821
ufrac_second = timeticks_from_second(frac);
811822
input = m[1].str() + m[3].str();
812823
}
813-
824+
814825
auto result = strptime(input.data(), "%Y-%m-%dT%H:%M:%SZ", &output);
815826

816827
if ( result == nullptr )

Release/tests/Functional/utils/base64.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,12 @@ TEST(bad_decode, "Ignore:Linux", "glib does not reject any of these inputs")
245245

246246
TEST(large_string)
247247
{
248-
size_t size = 128*1024;
248+
const size_t size = 64*1024;
249249

250-
std::vector<unsigned char> data;
250+
std::vector<unsigned char> data(size);
251251
for (auto i = 0u; i < size; ++i)
252252
{
253-
data.push_back((unsigned char)(rand() & 0xFF));
253+
data[i] = (unsigned char)(rand() & 0xFF);
254254
}
255255

256256
auto string = utility::conversions::to_base64(data);

0 commit comments

Comments
 (0)