diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a50feefa..efcaa1d1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -79,8 +79,8 @@ jobs:
- name: Build
run: |
- sudo apt-get install -y lcov sed
# Build with logging enabled.
+ sudo apt-get install -y lcov
cmake -S test -B build/ \
-G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Debug \
@@ -97,9 +97,9 @@ jobs:
- name: Run Coverage
run: |
make -C build/ coverage
- declare -a EXCLUDE=("\*test\*" "\*CMakeCCompilerId\*" "\*mocks\*")
- echo ${EXCLUDE[@]} | xargs lcov --rc lcov_branch_coverage=1 -r build/coverage.info -o build/coverage.info
- lcov --rc lcov_branch_coverage=1 --list build/coverage.info
+ declare -a EXCLUDE=("\*test\*" "\*CMakeCCompilerId.c")
+ echo ${EXCLUDE[@]} | xargs lcov --rc branch_coverage=1 --ignore-errors empty --ignore-errors source -r build/coverage.info -o build/coverage.info
+ lcov --rc branch_coverage=1 --ignore-errors empty --ignore-errors source --list build/coverage.info
- name: Check Coverage
uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main
@@ -198,7 +198,7 @@ jobs:
- name: Install Python3
uses: actions/setup-python@v3
with:
- python-version: "3.7.x"
+ python-version: "3.8"
- name: Measure sizes
uses: FreeRTOS/CI-CD-Github-Actions/memory_statistics@main
with:
diff --git a/docs/doxygen/code_examples/example_sntp_client_posix.c b/docs/doxygen/code_examples/example_sntp_client_posix.c
index 802b471b..d7f74b7a 100644
--- a/docs/doxygen/code_examples/example_sntp_client_posix.c
+++ b/docs/doxygen/code_examples/example_sntp_client_posix.c
@@ -139,7 +139,7 @@ static void sntpClient_SetTime( const SntpServerInfo_t * pTimeServer,
SntpLeapSecondInfo_t leapSecondInfo )
{
/* @[code_example_sntp_converttounixtime] */
- uint32_t unixSecs;
+ UnixTime_t unixSecs;
uint32_t unixMs;
SntpStatus_t status = Sntp_ConvertToUnixTime( pServerTime, &unixSecs, &unixMs );
diff --git a/docs/doxygen/include/size_table.md b/docs/doxygen/include/size_table.md
index 5ff9fdf4..76263e22 100644
--- a/docs/doxygen/include/size_table.md
+++ b/docs/doxygen/include/size_table.md
@@ -10,7 +10,7 @@
| core_sntp_client.c |
1.7K |
- 1.4K |
+ 1.3K |
| core_sntp_serializer.c |
@@ -20,6 +20,6 @@
| Total estimates |
2.7K |
- 2.2K |
+ 2.1K |
diff --git a/source/core_sntp_client.c b/source/core_sntp_client.c
index 42450982..d8f7b354 100644
--- a/source/core_sntp_client.c
+++ b/source/core_sntp_client.c
@@ -959,10 +959,6 @@ const char * Sntp_StatusToStr( SntpStatus_t status )
pString = "SntpZeroPollInterval";
break;
- case SntpErrorTimeNotSupported:
- pString = "SntpErrorTimeNotSupported";
- break;
-
case SntpErrorDnsFailure:
pString = "SntpErrorDnsFailure";
break;
diff --git a/source/core_sntp_serializer.c b/source/core_sntp_serializer.c
index bc65f3b8..3269130d 100644
--- a/source/core_sntp_serializer.c
+++ b/source/core_sntp_serializer.c
@@ -812,7 +812,7 @@ SntpStatus_t Sntp_CalculatePollInterval( uint16_t clockFreqTolerance,
}
SntpStatus_t Sntp_ConvertToUnixTime( const SntpTimestamp_t * pSntpTime,
- uint32_t * pUnixTimeSecs,
+ UnixTime_t * pUnixTimeSecs,
uint32_t * pUnixTimeMicrosecs )
{
SntpStatus_t status = SntpSuccess;
@@ -821,13 +821,6 @@ SntpStatus_t Sntp_ConvertToUnixTime( const SntpTimestamp_t * pSntpTime,
{
status = SntpErrorBadParameter;
}
- /* Check if passed time does not lie in the [UNIX epoch in 1970, UNIX time overflow in 2038] time range. */
- else if( ( pSntpTime->seconds > SNTP_TIME_AT_LARGEST_UNIX_TIME_SECS ) &&
- ( pSntpTime->seconds < SNTP_TIME_AT_UNIX_EPOCH_SECS ) )
- {
- /* The SNTP timestamp is outside the supported time range for conversion. */
- status = SntpErrorTimeNotSupported;
- }
else
{
/* Handle case when timestamp represents date in SNTP era 1
@@ -839,12 +832,13 @@ SntpStatus_t Sntp_ConvertToUnixTime( const SntpTimestamp_t * pSntpTime,
* +
* Sntp Time since Era 1 Epoch
*/
- *pUnixTimeSecs = UNIX_TIME_SECS_AT_SNTP_ERA_1_SMALLEST_TIME + pSntpTime->seconds;
+ *pUnixTimeSecs = ( UnixTime_t ) ( UNIX_TIME_SECS_AT_SNTP_ERA_1_SMALLEST_TIME + ( UnixTime_t ) ( pSntpTime->seconds ) );
}
+
/* Handle case when SNTP timestamp is in SNTP era 1 time range. */
- else
+ if( pSntpTime->seconds >= SNTP_TIME_AT_UNIX_EPOCH_SECS )
{
- *pUnixTimeSecs = pSntpTime->seconds - SNTP_TIME_AT_UNIX_EPOCH_SECS;
+ *pUnixTimeSecs = ( UnixTime_t ) ( ( UnixTime_t ) ( pSntpTime->seconds ) - SNTP_TIME_AT_UNIX_EPOCH_SECS );
}
/* Convert SNTP fractions to microseconds for UNIX time. */
diff --git a/source/include/core_sntp_serializer.h b/source/include/core_sntp_serializer.h
index 9f062d95..64295f85 100644
--- a/source/include/core_sntp_serializer.h
+++ b/source/include/core_sntp_serializer.h
@@ -43,6 +43,20 @@
#endif
/* *INDENT-ON* */
+/**
+ * @brief Type representing seconds since Unix epoch (January 1, 1970 UTC).
+ *
+ * The width of this type depends on the configuration macro USE_LEGACY_TIME_API:
+ * - If USE_LEGACY_TIME_API is defined, a 32-bit unsigned integer is used.
+ * This limits date representation to the year 2038 (Y2038 limitation).
+ * - Otherwise, a 64-bit unsigned integer is used for Y2038 compliance.
+ */
+#ifdef USE_LEGACY_TIME_API
+ typedef uint32_t UnixTime_t; /**< 32-bit Unix time for legacy systems. */
+#else
+ typedef uint64_t UnixTime_t; /**< 64-bit Unix time for Y2038 compliance. */
+#endif
+
/**
* @ingroup sntp_constants
* @brief The base packet size of request and response of the (S)NTP protocol.
@@ -189,12 +203,6 @@ typedef enum SntpStatus
*/
SntpZeroPollInterval,
- /**
- * @brief SNTP timestamp cannot be converted to UNIX time as time does not lie
- * in time range supported by Sntp_ConvertToUnixTime.
- */
- SntpErrorTimeNotSupported,
-
/**
* @brief The user-defined DNS resolution interface, @ref SntpResolveDns_t, failed to resolve
* address for a time server. This status is returned by the @ref Sntp_SendTimeRequest API.
@@ -496,17 +504,18 @@ SntpStatus_t Sntp_CalculatePollInterval( uint16_t clockFreqTolerance,
* @brief Utility to convert SNTP timestamp (that uses 1st Jan 1900 as the epoch) to
* UNIX timestamp (that uses 1st Jan 1970 as the epoch).
*
- * @note This function can ONLY handle conversions of SNTP timestamps that lie in the
- * range from 1st Jan 1970 0h 0m 0s, the UNIX epoch time, to 19th Jan 2038 3h 14m 7s,
- * the maximum UNIX time that can be represented in a signed 32 bit integer. (The
- * limitation is to support systems that use signed 32-bit integer to represent the
- * seconds part of the UNIX time.)
+ * @note This function converts SNTP timestamps to UNIX time supporting both 32-bit and
+ * 64-bit representations based on the configuration macro USE_LEGACY_TIME_API.
+ *
+ * - If USE_LEGACY_TIME_API is defined, the conversion is limited to the date range
+ * from 1st Jan 1970 0h 0m 0s (UNIX epoch) to 19th Jan 2038 3h 14m 7s, due to the
+ * 32-bit width limitation.
*
- * @note This function supports overflow of the SNTP timestamp (from the 7 Feb 2036
- * 6h 28m 16s time, i.e. SNTP era 1) by treating the timestamps with seconds part
- * in the range [0, 61,505,152] seconds where the upper limit represents the UNIX
- * overflow time (i.e. 19 Jan 2038 3h 14m 7s) for systems that use signed 32-bit
- * integer to represent time.
+ * - If USE_LEGACY_TIME_API is not defined, 64-bit UNIX time representation is used,
+ * allowing conversion of SNTP timestamps beyond the year 2038 (Y2038 problem mitigated).
+ *
+ * @note The function also correctly handles SNTP era overflow (from 7 Feb 2036 6h 28m 16s,
+ * i.e., SNTP era 1) to ensure accurate conversion across SNTP eras.
*
* @param[in] pSntpTime The SNTP timestamp to convert to UNIX time.
* @param[out] pUnixTimeSecs This will be filled with the seconds part of the
@@ -517,15 +526,14 @@ SntpStatus_t Sntp_CalculatePollInterval( uint16_t clockFreqTolerance,
* @return Returns one of the following:
* - #SntpSuccess if conversion to UNIX time is successful
* - #SntpErrorBadParameter if any of the passed parameters are NULL.
- * - #SntpErrorTimeNotSupported if the passed SNTP time does not lie in the
- * supported time range.
*/
/* @[define_sntp_converttounixtime] */
SntpStatus_t Sntp_ConvertToUnixTime( const SntpTimestamp_t * pSntpTime,
- uint32_t * pUnixTimeSecs,
+ UnixTime_t * pUnixTimeSecs,
uint32_t * pUnixTimeMicrosecs );
/* @[define_sntp_converttounixtime] */
+
/* *INDENT-OFF* */
#ifdef __cplusplus
}
diff --git a/test/cbmc/proofs/Sntp_ConvertToUnixTime/Sntp_ConvertToUnixTime_harness.c b/test/cbmc/proofs/Sntp_ConvertToUnixTime/Sntp_ConvertToUnixTime_harness.c
index c6848119..797bab90 100644
--- a/test/cbmc/proofs/Sntp_ConvertToUnixTime/Sntp_ConvertToUnixTime_harness.c
+++ b/test/cbmc/proofs/Sntp_ConvertToUnixTime/Sntp_ConvertToUnixTime_harness.c
@@ -32,15 +32,15 @@
void harness()
{
SntpTimestamp_t * pSntpTime;
- uint32_t * pUnixTimeSecs;
+ UnixTime_t * pUnixTimeSecs;
uint32_t * pUnixTimeMicrosecs;
SntpStatus_t sntpStatus;
pSntpTime = malloc( sizeof( SntpTimestamp_t ) );
- pUnixTimeSecs = malloc( sizeof( uint32_t ) );
+ pUnixTimeSecs = malloc( sizeof( UnixTime_t ) );
pUnixTimeMicrosecs = malloc( sizeof( uint32_t ) );
sntpStatus = Sntp_ConvertToUnixTime( pSntpTime, pUnixTimeSecs, pUnixTimeMicrosecs );
- __CPROVER_assert( ( sntpStatus == SntpErrorBadParameter || sntpStatus == SntpErrorTimeNotSupported || sntpStatus == SntpSuccess ), "The return value is not a valid SNTP Status" );
+ __CPROVER_assert( ( sntpStatus == SntpErrorBadParameter || sntpStatus == SntpSuccess ), "The return value is not a valid SNTP Status" );
}
diff --git a/test/unit-test/core_sntp_client_utest.c b/test/unit-test/core_sntp_client_utest.c
index d39727f9..2f7d5d63 100644
--- a/test/unit-test/core_sntp_client_utest.c
+++ b/test/unit-test/core_sntp_client_utest.c
@@ -1374,7 +1374,6 @@ void test_StatusToStr( void )
TEST_ASSERT_EQUAL_STRING( "SntpErrorBufferTooSmall", Sntp_StatusToStr( SntpErrorBufferTooSmall ) );
TEST_ASSERT_EQUAL_STRING( "SntpInvalidResponse", Sntp_StatusToStr( SntpInvalidResponse ) );
TEST_ASSERT_EQUAL_STRING( "SntpZeroPollInterval", Sntp_StatusToStr( SntpZeroPollInterval ) );
- TEST_ASSERT_EQUAL_STRING( "SntpErrorTimeNotSupported", Sntp_StatusToStr( SntpErrorTimeNotSupported ) );
TEST_ASSERT_EQUAL_STRING( "SntpErrorDnsFailure", Sntp_StatusToStr( SntpErrorDnsFailure ) );
TEST_ASSERT_EQUAL_STRING( "SntpErrorNetworkFailure", Sntp_StatusToStr( SntpErrorNetworkFailure ) );
TEST_ASSERT_EQUAL_STRING( "SntpServerNotAuthenticated", Sntp_StatusToStr( SntpServerNotAuthenticated ) );
diff --git a/test/unit-test/core_sntp_serializer_utest.c b/test/unit-test/core_sntp_serializer_utest.c
index d293b9b9..90b5bd5c 100644
--- a/test/unit-test/core_sntp_serializer_utest.c
+++ b/test/unit-test/core_sntp_serializer_utest.c
@@ -877,32 +877,20 @@ void test_ConvertToUnixTime_InvalidParams( void )
/* Use same memory for UNIX seconds and microseconds as we are not
* testing those values. */
- uint32_t unixTime;
+ UnixTime_t unixTime;
+ uint32_t unixTimeMs;
/* Test with NULL SNTP time. */
TEST_ASSERT_EQUAL( SntpErrorBadParameter, Sntp_ConvertToUnixTime( NULL,
&unixTime,
- &unixTime ) );
+ &unixTimeMs ) );
/* Test with NULL output parameters. */
TEST_ASSERT_EQUAL( SntpErrorBadParameter, Sntp_ConvertToUnixTime( &sntpTime,
NULL,
- &unixTime ) );
+ &unixTimeMs ) );
TEST_ASSERT_EQUAL( SntpErrorBadParameter, Sntp_ConvertToUnixTime( &sntpTime,
&unixTime,
NULL ) );
-
- /* Test with time before UNIX epoch or 1st Jan 1970 .*/
- sntpTime.seconds = SNTP_TIME_AT_UNIX_EPOCH_SECS - 5;
- TEST_ASSERT_EQUAL( SntpErrorTimeNotSupported, Sntp_ConvertToUnixTime( &sntpTime,
- &unixTime,
- &unixTime ) );
-
- /* Test with timestamp that after largest UNIX time for signed 32-bit integer systems
- * (i.e. after 18 Jan 2036 3:14:07) */
- sntpTime.seconds = SNTP_TIME_AT_LARGEST_UNIX_TIME_SECS + 5;
- TEST_ASSERT_EQUAL( SntpErrorTimeNotSupported, Sntp_ConvertToUnixTime( &sntpTime,
- &unixTime,
- &unixTime ) );
}
/**
@@ -912,7 +900,7 @@ void test_ConvertToUnixTime_InvalidParams( void )
void test_ConvertToUnixTime_Nominal( void )
{
SntpTimestamp_t sntpTime = TEST_TIMESTAMP;
- uint32_t unixTimeSecs;
+ UnixTime_t unixTimeSecs;
uint32_t unixTimeMs;
#define TEST_SNTP_TO_UNIX_CONVERSION( sntpTimeSecs, sntpTimeFracs, \
diff --git a/tools/cmock/coverage.cmake b/tools/cmock/coverage.cmake
index 3cdbd316..500aab22 100644
--- a/tools/cmock/coverage.cmake
+++ b/tools/cmock/coverage.cmake
@@ -14,9 +14,12 @@ execute_process( COMMAND lcov --directory ${CMAKE_BINARY_DIR}
--base-directory ${CMAKE_BINARY_DIR}
--initial
--capture
- --rc lcov_branch_coverage=1
+ --rc branch_coverage=1
+ --ignore-errors empty
+ --ignore-errors source
--rc genhtml_branch_coverage=1
--output-file=${CMAKE_BINARY_DIR}/base_coverage.info
+ --quiet
)
file(GLOB files "${CMAKE_BINARY_DIR}/bin/tests/*")
@@ -45,11 +48,14 @@ execute_process(COMMAND ruby
# capture data after running the tests
execute_process(
COMMAND lcov --capture
- --rc lcov_branch_coverage=1
+ --rc branch_coverage=1
+ --ignore-errors empty
+ --ignore-errors source
--rc genhtml_branch_coverage=1
--base-directory ${CMAKE_BINARY_DIR}
--directory ${CMAKE_BINARY_DIR}
--output-file ${CMAKE_BINARY_DIR}/second_coverage.info
+ --quiet
)
# combile baseline results (zeros) with the one after running the tests
@@ -60,11 +66,17 @@ execute_process(
--add-tracefile ${CMAKE_BINARY_DIR}/second_coverage.info
--output-file ${CMAKE_BINARY_DIR}/coverage.info
--no-external
- --rc lcov_branch_coverage=1
+ --rc branch_coverage=1
+ --ignore-errors empty
+ --ignore-errors source
+ --quiet
)
execute_process(
- COMMAND genhtml --rc lcov_branch_coverage=1
+ COMMAND genhtml --rc branch_coverage=1
+ --ignore-errors empty
+ --ignore-errors source
--branch-coverage
--output-directory ${CMAKE_BINARY_DIR}/coverage
${CMAKE_BINARY_DIR}/coverage.info
+ --quiet
)