diff --git a/.github/scripts/rtrouted.sh b/.github/scripts/rtrouted.sh index 7c35d464..be9ea7ce 100755 --- a/.github/scripts/rtrouted.sh +++ b/.github/scripts/rtrouted.sh @@ -13,4 +13,3 @@ nohup rtrouted -f -l DEBUG > /tmp/rtrouted_log.txt & mkdir ${RBUS_INSTALL_DIR}/usr/lib/rbus_temp_lib cp ${RBUS_INSTALL_DIR}/usr/lib/librbuscore.so* ${RBUS_INSTALL_DIR}/usr/lib/rbus_temp_lib/ cp ${RBUS_INSTALL_DIR}/usr/lib/librtMessage.so* ${RBUS_INSTALL_DIR}/usr/lib/rbus_temp_lib/ -cp ${RBUS_INSTALL_DIR}/usr/lib/libcjson.so ${RBUS_INSTALL_DIR}/usr/lib/rbus_temp_lib/ diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 248f04ff..9236e1a8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -4,7 +4,7 @@ name: CI on: - pull_request_target: + pull_request: push: paths-ignore: - 'AUTHORS' @@ -20,10 +20,10 @@ on: jobs: test: name: Unit Tests - runs-on: [ ubuntu-latest ] + runs-on: [ ubuntu-20.04 ] steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 @@ -31,13 +31,13 @@ jobs: - name: Install packages run: | sudo apt update - sudo apt-get -y install valgrind libcunit1 libcunit1-doc libcunit1-dev libmsgpack-dev gcovr libtool xsltproc docbook-xsl uuid-dev - pip install codecov + sudo apt-get -y install valgrind libcunit1 libcunit1-doc libcunit1-dev libmsgpack-dev gcovr libtool xsltproc docbook-xsl + pip install coverage - name: Make Build Directory run: mkdir build - - name: Install sonar-scanner and build-wrapper + - name: Get Sonarcloud Binaries uses: sonarsource/sonarcloud-github-c-cpp@v2 - name: Get rtrouted Binary @@ -61,7 +61,7 @@ jobs: mkdir _install mkdir _install/lib cp ${RBUS_INSTALL_DIR}/usr/lib/librbus* _install/lib - build-wrapper-linux-x86-64 --out-dir bw-output make all test + make all test - name: Stop rtrouted run: | @@ -70,19 +70,20 @@ jobs: - name: Merge GCOV Reports for Sonarcloud working-directory: build run: | - gcovr --sonarqube coverage.xml -r .. + gcovr --xml coverage.xml -r .. || echo "Coverage generation skipped" + + - name: Upload SonarCloud + run: | + sonar-scanner -Dsonar.host.url=https://sonarcloud.io -Dproject.settings=.sonar-project.properties -Dsonar.login=${{ secrets.SONAR_TOKEN }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload Codecov.io - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + #uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: directory: . fail_ci_if_error: true - token: ${{ secrets.CODECOV_TOKEN }} - - name: Upload SonarCloud - run: | - build/sonar-scanner/bin/sonar-scanner -Dsonar.host.url=https://sonarcloud.io -Dproject.settings=.sonar-project.properties -Dsonar.login=${{ secrets.SONAR_TOKEN }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.sonar-project.properties b/.sonar-project.properties new file mode 100644 index 00000000..9b389b5d --- /dev/null +++ b/.sonar-project.properties @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2023 Comcast Cable Communications Management, LLC +# SPDX-License-Identifier: Apache-2.0 + +# Reference: +# https://github.com/SonarSource/sonarcloud_example_go-sqscanner-travis/blob/master/sonar-project.properties + + +# ===================================================== +# Standard properties +# ===================================================== + +sonar.organization=xmidt-org +sonar.projectKey=xmidt-org_webcfg +sonar.projectName=webcfg + +sonar.sources=src + +# ===================================================== +# Meta-data for the project +# ===================================================== + +sonar.links.homepage=https://github.com/xmidt-org/webcfg +sonar.links.ci=https://github.com/xmidt-org/webcfg/actions +sonar.links.scm=https://github.com/xmidt-org/webcfg +sonar.links.issue=https://github.com/xmidt-org/webcfg/issues + +# ===================================================== +# Properties specific to C +# ===================================================== +sonar.cfamily.build-wrapper-output=build/bw-output +sonar.cfamily.threads=2 +sonar.cfamily.cache.enabled=false +sonar.coverageReportPaths=build/coverage.xml diff --git a/src/webcfg_multipart.c b/src/webcfg_multipart.c index 52528241..7dbc32a1 100644 --- a/src/webcfg_multipart.c +++ b/src/webcfg_multipart.c @@ -266,6 +266,11 @@ WEBCFG_STATUS webcfg_http_request(char **configData, int r_count, int status, lo //Replace {mac} string from default init url with actual deviceMAC WebcfgDebug("replaceMacWord to actual device mac\n"); webConfigURL = replaceMacWord(configURL, c, get_deviceMAC()); + if(webConfigURL == NULL) + { + WebcfgError("replaceMacWord failed. Failed to set webConfigURL\n"); + return WEBCFG_FAILURE; + } //Check the url is having empty mac or actual devicemac checkValidURL(&webConfigURL); if(get_global_supplementarySync() == 0) @@ -2252,6 +2257,11 @@ WEBCFG_STATUS print_tmp_doc_list(size_t mp_count) void checkValidURL(char **s) { + if (!s || *s == NULL) + { + WebcfgError("webConfigURL is Empty or NULL\n"); + return; + } char modified_url[256] = {0}; int maxRetryTime = 31; int backoffRetryTime = 0; @@ -2271,10 +2281,10 @@ void checkValidURL(char **s) { while (1) { if (backoffRetryTime <= maxRetryTime) { - backoffRetryTime = (int)pow(2, c) - 1; + backoffRetryTime = (1 << c) - 1; } const char *mac = get_deviceMAC(); - if (mac != NULL && strncmp(mac, "000000000000", 12) != 0) + if (mac != NULL && mac[0] != '\0' && strncmp(mac, "000000000000", 12) != 0) { WebcfgDebug("Mac fetched is %s\n", mac); strncat(modified_url, mac, sizeof(modified_url) - strlen(modified_url) - 1); @@ -2305,7 +2315,7 @@ void checkValidURL(char **s) { // Validate if the MAC is correct for the box const char *mac = get_deviceMAC(); - if (mac != NULL && strncmp(mac, start, 12) != 0) + if (mac != NULL && mac[0] != '\0' && strncmp(mac, start, 12) != 0) { WebcfgError("MAC Address in URL does not match actual device MAC. Updating...\n"); strncpy(modified_url, *s, start - *s); @@ -2323,39 +2333,57 @@ void checkValidURL(char **s) { char *replaceMacWord(const char *s, const char *macW, const char *deviceMACW) { + if (!s || !macW) + { + WebcfgInfo("macW or configURL is NULL\n"); + return NULL; + } char *result = NULL; int i, cnt = 0; - if(deviceMACW != NULL) + // When device mac is NULL replace with a fallback mac + if (deviceMACW == NULL || deviceMACW[0] == '\0') + { + WebcfgInfo("Device mac is NULL or Empty. Setting fallback mac\n"); + deviceMACW = "000000000000"; + } + + int deviceMACWlen = strlen(deviceMACW); + int macWlen = strlen(macW); + + // Counting the number of times mac word occur in the string + for (i = 0; s[i] != '\0'; i++) { - int deviceMACWlen = strlen(deviceMACW); - int macWlen = strlen(macW); - // Counting the number of times mac word occur in the string - for (i = 0; s[i] != '\0'; i++) + if (strstr(&s[i], macW) == &s[i]) { - if (strstr(&s[i], macW) == &s[i]) - { - cnt++; - // Jumping to index after the mac word. - i += macWlen - 1; - } + cnt++; + // Jumping to index after the mac word. + i += macWlen - 1; } + } + + result = (char *)malloc(i + cnt * (deviceMACWlen - macWlen) + 1); + if(result == NULL) + { + WebcfgError("malloc failed for result\n"); + return NULL; + } - result = (char *)malloc(i + cnt * (deviceMACWlen - macWlen) + 1); - i = 0; - while (*s) + i = 0; + while (*s) + { + if (strstr(s, macW) == s) { - if (strstr(s, macW) == s) - { - strcpy(&result[i], deviceMACW); - i += deviceMACWlen; - s += macWlen; - } - else - result[i++] = *s++; + strcpy(&result[i], deviceMACW); + i += deviceMACWlen; + s += macWlen; + } + else + { + result[i++] = *s++; } - result[i] = '\0'; } + result[i] = '\0'; return result; } diff --git a/tests/test_multipart_unittest.c b/tests/test_multipart_unittest.c index 12cc19dc..943050b4 100644 --- a/tests/test_multipart_unittest.c +++ b/tests/test_multipart_unittest.c @@ -70,13 +70,13 @@ struct mock_token_data { struct mock_token_data mock_data; -char device_mac[32] = {'\0'}; +char *mock_device_mac = "b42xxxxxxxxx"; char* get_deviceMAC() { - char *device_mac = strdup("b42xxxxxxxxx"); - return device_mac; + return mock_device_mac; } + char * getRebootReason() { char *reason = strdup("factory-reset"); @@ -376,11 +376,27 @@ void test_replaceMac(){ CU_ASSERT_STRING_EQUAL(webConfigURL,"https://config/b42xxxxxxxxx/com"); } +void test_replaceMac_NullUrl(){ + char *configURL= NULL; + char c[] = "{sss}"; + char *webConfigURL = replaceMacWord(configURL, c, get_deviceMAC()); + CU_ASSERT_PTR_NULL(webConfigURL); +} + +void test_replaceMac_NullMac(){ + char *configURL= "https://config/{sss}/com"; + char c[] = "{sss}"; + mock_device_mac = NULL; + char *webConfigURL = replaceMacWord(configURL, c, get_deviceMAC()); + CU_ASSERT_STRING_EQUAL(webConfigURL,"https://config/000000000000/com"); + mock_device_mac = "b42xxxxxxxxx"; // Restore for other tests +} + void test_checkValidURL_ValidURL(){ - char *webConfigURL = strdup("https://sample/device/123456ffaa/config"); + char *webConfigURL = strdup("https://sample/device/b42xxxxxxxxx/config"); checkValidURL(&webConfigURL); - const char *expected_url ="https://sample/device/123456ffaa/config"; + const char *expected_url ="https://sample/device/b42xxxxxxxxx/config"; CU_ASSERT_STRING_EQUAL(webConfigURL,expected_url); } @@ -392,6 +408,20 @@ void test_checkValidURL_InvalidURL(){ CU_ASSERT_STRING_EQUAL(webConfigURL,expected_url); } +void test_checkValidURL_NullInput(){ + char *webConfigURL = NULL; + checkValidURL(&webConfigURL); + CU_ASSERT_PTR_NULL(webConfigURL); +} + +void test_checkValidURL_InvalidMac(){ + + char *webConfigURL = strdup("https://sample/device/c44xxxxxxxxx/config"); + checkValidURL(&webConfigURL); + const char *expected_url ="https://sample/device/b42xxxxxxxxx/config"; + CU_ASSERT_STRING_EQUAL(webConfigURL,expected_url); +} + void test_createHeader(){ @@ -1459,8 +1489,12 @@ void add_suites( CU_pSuite *suite ) *suite = CU_add_suite( "tests", NULL, NULL ); CU_add_test( *suite, "test generate_trans_uuid", test_generate_trans_uuid); CU_add_test( *suite, "test replaceMacWord", test_replaceMac); + CU_add_test( *suite, "test replaceMacWord_NullMac", test_replaceMac_NullMac); + CU_add_test( *suite, "test replaceMac_NullUrl", test_replaceMac_NullUrl); CU_add_test( *suite, "test checkValidURL_ValidURL", test_checkValidURL_ValidURL); CU_add_test( *suite, "test checkValidURL_InvalidURL", test_checkValidURL_InvalidURL); + CU_add_test( *suite, "test checkValidURL_NullInput", test_checkValidURL_NullInput); + CU_add_test( *suite, "test checkValidURL_InvalidMac", test_checkValidURL_InvalidMac); CU_add_test( *suite, "test createCurlHeader", test_createHeader); CU_add_test( *suite, "test createHeader_doc_header_max_data", test_createHeader_doc_header_max_data); CU_add_test( *suite, "test createHeader_primary_sync", test_createHeader_primary_sync);