From 3c8819e10f9eff89195566e7e02f349373f5c4c7 Mon Sep 17 00:00:00 2001 From: David Steele Date: Fri, 9 Jul 2021 14:16:10 -0400 Subject: [PATCH] Add CodeQL static code analysis. Also fix some minor issues identified, specifically using gmtime_r()/localtime_r() vs gmtime()/localtime(). --- .github/workflows/test.yml | 33 +++++++++++++++++++++++++++++++++ doc/xml/release.xml | 11 +++++++++++ src/command/backup/common.c | 5 ++++- src/command/info/info.c | 5 +++-- src/command/restore/restore.c | 4 +++- src/common/io/http/common.c | 11 ++++++----- src/common/log.c | 4 +++- src/common/type/convert.c | 3 ++- src/storage/s3/storage.c | 3 ++- 9 files changed, 67 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6126d225b..e2be2e700 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,10 @@ on: - '**-ci' - '**-cig' pull_request: + branches: + - integration + - '**-ci' + - '**-cig' jobs: test: @@ -50,3 +54,32 @@ jobs: - name: Run Test run: cd ${HOME?} && ${GITHUB_WORKSPACE?}/pgbackrest/test/ci.pl ${{matrix.param}} --param=build-max=2 + + codeql: + runs-on: ubuntu-latest + + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: + - cpp + + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{matrix.language}} + + - name: Build + run: ${GITHUB_WORKSPACE?}/src/configure && make -j 2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/doc/xml/release.xml b/doc/xml/release.xml index 37b0a7e91..831f9bef3 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -127,6 +127,17 @@ + + + + + + + + +

Add CodeQL static code analysis.

+
+ diff --git a/src/command/backup/common.c b/src/command/backup/common.c index 45a9cc2c1..a5b074846 100644 --- a/src/command/backup/common.c +++ b/src/command/backup/common.c @@ -30,9 +30,12 @@ backupLabelFormat(BackupType type, const String *backupLabelPrior, time_t timest ASSERT(timestamp > 0); // Format the timestamp + struct tm timePart; char buffer[16]; + THROW_ON_SYS_ERROR( - strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", localtime(×tamp)) == 0, AssertError, "unable to format time"); + strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", localtime_r(×tamp, &timePart)) == 0, AssertError, + "unable to format time"); // If full label String *result = NULL; diff --git a/src/command/info/info.c b/src/command/info/info.c index 2876390ca..71b28818c 100644 --- a/src/command/info/info.c +++ b/src/command/info/info.c @@ -785,13 +785,14 @@ formatTextBackup(const DbGroup *dbGroup, String *resultStr) // Get and format the backup start/stop time KeyValue *timestampInfo = varKv(kvGet(backupInfo, BACKUP_KEY_TIMESTAMP_VAR)); + struct tm timePart; char timeBufferStart[20]; char timeBufferStop[20]; time_t timeStart = (time_t)varUInt64(kvGet(timestampInfo, KEY_START_VAR)); time_t timeStop = (time_t)varUInt64(kvGet(timestampInfo, KEY_STOP_VAR)); - strftime(timeBufferStart, sizeof(timeBufferStart), "%Y-%m-%d %H:%M:%S", localtime(&timeStart)); - strftime(timeBufferStop, sizeof(timeBufferStop), "%Y-%m-%d %H:%M:%S", localtime(&timeStop)); + strftime(timeBufferStart, sizeof(timeBufferStart), "%Y-%m-%d %H:%M:%S", localtime_r(&timeStart, &timePart)); + strftime(timeBufferStop, sizeof(timeBufferStop), "%Y-%m-%d %H:%M:%S", localtime_r(&timeStop, &timePart)); strCatFmt(resultStr, " timestamp start/stop: %s / %s\n", timeBufferStart, timeBufferStop); strCatZ(resultStr, " wal start/stop: "); diff --git a/src/command/restore/restore.c b/src/command/restore/restore.c index 12ac9a332..5ab44e24e 100644 --- a/src/command/restore/restore.c +++ b/src/command/restore/restore.c @@ -1831,9 +1831,11 @@ restoreRecoveryWrite(const Manifest *manifest) else { // Generate a label used to identify this restore in the recovery file + struct tm timePart; char restoreTimestamp[20]; time_t timestamp = time(NULL); - strftime(restoreTimestamp, sizeof(restoreTimestamp), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + + strftime(restoreTimestamp, sizeof(restoreTimestamp), "%Y-%m-%d %H:%M:%S", localtime_r(×tamp, &timePart)); const String *restoreLabel = STR(restoreTimestamp); // Write recovery file based on PostgreSQL version diff --git a/src/common/io/http/common.c b/src/common/io/http/common.c index d8770dbb1..07f93f6ff 100644 --- a/src/common/io/http/common.c +++ b/src/common/io/http/common.c @@ -53,19 +53,20 @@ httpDateToTime(const String *lastModified) } String * -httpDateFromTime(time_t time) +httpDateFromTime(const time_t time) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(TIME, time); FUNCTION_TEST_END(); - struct tm *timePart = gmtime(&time); + struct tm timePart; + gmtime_r(&time, &timePart); FUNCTION_TEST_RETURN( strNewFmt( - "%s, %02d %s %04d %02d:%02d:%02d GMT", httpCommonDayList[timePart->tm_wday], timePart->tm_mday, - httpCommonMonthList[timePart->tm_mon], timePart->tm_year + 1900, timePart->tm_hour, timePart->tm_min, - timePart->tm_sec)); + "%s, %02d %s %04d %02d:%02d:%02d GMT", httpCommonDayList[timePart.tm_wday], timePart.tm_mday, + httpCommonMonthList[timePart.tm_mon], timePart.tm_year + 1900, timePart.tm_hour, timePart.tm_min, + timePart.tm_sec)); } /**********************************************************************************************************************************/ diff --git a/src/common/log.c b/src/common/log.c index 43b8d3795..fcc999989 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -371,11 +371,13 @@ logPre(LogLevel logLevel, unsigned int processId, const char *fileName, const ch // Add time if (logTimestamp) { + struct tm timePart; TimeMSec logTimeMSec = timeMSec(); time_t logTimeSec = (time_t)(logTimeMSec / MSEC_PER_SEC); result.bufferPos += strftime( - logBuffer + result.bufferPos, sizeof(logBuffer) - result.bufferPos, "%Y-%m-%d %H:%M:%S", localtime(&logTimeSec)); + logBuffer + result.bufferPos, sizeof(logBuffer) - result.bufferPos, "%Y-%m-%d %H:%M:%S", + localtime_r(&logTimeSec, &timePart)); result.bufferPos += (size_t)snprintf( logBuffer + result.bufferPos, sizeof(logBuffer) - result.bufferPos, ".%03d ", (int)(logTimeMSec % 1000)); } diff --git a/src/common/type/convert.c b/src/common/type/convert.c index b06fa2f3a..13af3ca1a 100644 --- a/src/common/type/convert.c +++ b/src/common/type/convert.c @@ -374,7 +374,8 @@ cvtTimeToZ(time_t value, char *buffer, size_t bufferSize) ASSERT(buffer != NULL); - size_t result = strftime(buffer, bufferSize, "%s", localtime(&value)); + struct tm timePart; + size_t result = strftime(buffer, bufferSize, "%s", localtime_r(&value, &timePart)); if (result == 0) THROW(AssertError, "buffer overflow"); diff --git a/src/storage/s3/storage.c b/src/storage/s3/storage.c index 3c06fc97b..29ac9aad8 100644 --- a/src/storage/s3/storage.c +++ b/src/storage/s3/storage.c @@ -141,10 +141,11 @@ storageS3DateTime(time_t authTime) FUNCTION_TEST_PARAM(TIME, authTime); FUNCTION_TEST_END(); + struct tm timePart; char buffer[ISO_8601_DATE_TIME_SIZE + 1]; THROW_ON_SYS_ERROR( - strftime(buffer, sizeof(buffer), "%Y%m%dT%H%M%SZ", gmtime(&authTime)) != ISO_8601_DATE_TIME_SIZE, AssertError, + strftime(buffer, sizeof(buffer), "%Y%m%dT%H%M%SZ", gmtime_r(&authTime, &timePart)) != ISO_8601_DATE_TIME_SIZE, AssertError, "unable to format date"); FUNCTION_TEST_RETURN(strNewZ(buffer));