Repository: NordicSemiconductor/zcbor (language: python)

Issue:
Issue with zcbor_uint32_put in zephyr using qemu_malta_be platform
There seems to be an issue using `zcbor_uint32_put` on the `qemu_malta_be` platform in zephyr, with this code:
```
        ctx->ok = 
zcbor_tstr_encode_ptr(ctx->zse, group->group_name, strlen(group->group_name));//        &&
printk(" -> %d\n", ctx->ok);
        ctx->ok = 
                  zcbor_map_start_encode(ctx->zse, HASH_CHECKSUM_SUPPORTED_COLUMNS_MAX) ;//     &&
printk(" -> %d\n", ctx->ok);
        ctx->ok = 
                  zcbor_tstr_put_lit(ctx->zse, "format")                                ;//     &&
printk(" -> %d\n", ctx->ok);
        ctx->ok = 
                  zcbor_uint32_put(ctx->zse, (uint32_t)group->byte_string)              ;//     &&
printk(" -> %d\n", ctx->ok);
        ctx->ok = 
                  zcbor_tstr_put_lit(ctx->zse, "size")                                  ;//     &&
printk(" -> %d\n", ctx->ok);
        ctx->ok = 
                  zcbor_uint32_put(ctx->zse, (uint32_t)group->output_size)              ;//     &&
printk(" -> %d\n", ctx->ok);
        ctx->ok = 
                  zcbor_map_end_encode(ctx->zse, HASH_CHECKSUM_SUPPORTED_COLUMNS_MAX);
printk(" -> %d\n", ctx->ok);
```

This specific line returns 0:
`                  zcbor_uint32_put(ctx->zse, (uint32_t)group->byte_string)              ;//     &&`
If it is changed to:
`                  zcbor_uint64_put(ctx->zse, (uint64_t)group->byte_string)              ;//     &&`
Then the return code is 1 (success).

If the error is ignored then the generated outputs, as expected, differ. Bad output with uint32:
`01 00 00 1f 00 08 01 03 bf 65 74 79 70 65 73 bf 65 63 72 63 33 32 bf 66 66 6f 72 6d 61 74 64 73 69 7a 65 04 ff ff ff`
Good output with uint64:
`01 00 00 20 00 08 01 03 bf 65 74 79 70 65 73 bf 65 63 72 63 33 32 bf 66 66 6f 72 6d 61 74 00 64 73 69 7a 65 04 ff ff ff`

This is using zephyr main as of present, zcbor commit a0d6981f14d4001d6f0d608d1a427f9bc6bb6d02


Discussion / hints:
I think it leads back to this:
```
static const void *get_result(const void *const input, uint_fast32_t max_result_len,
        uint_fast32_t result_len)
{
#ifdef CONFIG_BIG_ENDIAN
        return &((uint8_t *)input)[max_result_len - result_len];
#else
        return input;
#endif
}
```
The input provided is 0, the size is 8, which makes the result len 0, this is now out of bounds, which is then being used later on to check the "additional" and assert if it's greater than 32 (it shows 128 in the debugging)

@oyvindronningstad A quick change of ensuring `get_result_len` returns >= 1 makes this work, not sure if it would impact other encode functions. I'm surprised this has never failed before, and can't work out why it's only one qemu platform in zephyr that if fails on

Fix patch:
diff --git a/src/zcbor_encode.c b/src/zcbor_encode.c
index 37256355..e587117a 100644
--- a/src/zcbor_encode.c
+++ b/src/zcbor_encode.c
@@ -111,7 +111,7 @@ static const void *get_result(const void *const input, uint_fast32_t max_result_
 	uint_fast32_t result_len)
 {
 #ifdef CONFIG_BIG_ENDIAN
-	return &((uint8_t *)input)[max_result_len - result_len];
+	return &((uint8_t *)input)[max_result_len - (result_len ? result_len : 1)];
 #else
 	return input;
 #endif


Test patch:
diff --git a/.github/actions/prepare_and_run_tests/action.yaml b/.github/actions/prepare_and_run_tests/action.yaml
index bb5de9ce..54440d20 100644
--- a/.github/actions/prepare_and_run_tests/action.yaml
+++ b/.github/actions/prepare_and_run_tests/action.yaml
@@ -7,6 +7,10 @@ inputs:
     description: 'Which zephyr toolchain to use.'
     required: false
     default: 'host'
+  zephyr_toolchain_arch:
+    description: 'Which architectures to use.'
+    required: false
+    default: ''
 runs:
   using: 'composite'
   steps:
@@ -38,20 +42,34 @@ runs:
         pip3 install -U -r $ZEPHYR_BASE/scripts/requirements-build-test.txt
         pip3 install -U -r $ZEPHYR_BASE/scripts/requirements-run-test.txt
 
-    - name: Install Zephyr SDK (ARM)
+    - name: Install Zephyr SDK
       if: ${{ inputs.zephyr_toolchain == 'zephyr' }}
       shell: sh
       run: |
-        sudo apt install qemu qemu-system-arm
-        ZEPHYR_SDK_VERSION=0.15.0
         wget -nv https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$ZEPHYR_SDK_VERSION/zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64_minimal.tar.gz
-        wget -nv https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$ZEPHYR_SDK_VERSION/toolchain_linux-x86_64_arm-zephyr-eabi.tar.gz
         wget -nv -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$ZEPHYR_SDK_VERSION/sha256.sum | shasum --check --ignore-missing
         tar -xf zephyr-sdk-${ZEPHYR_SDK_VERSION}_linux-x86_64_minimal.tar.gz
         mv zephyr-sdk-$ZEPHYR_SDK_VERSION zephyr-sdk
-        tar -xf toolchain_linux-x86_64_arm-zephyr-eabi.tar.gz -C zephyr-sdk
         west update cmsis
 
+    - name: Install Zephyr SDK (ARM)
+      if: ${{ inputs.zephyr_toolchain == 'zephyr' && contains(inputs.zephyr_toolchain_arch, 'arm') }}
+      shell: sh
+      run: |
+        sudo apt install qemu qemu-system-arm
+        wget -nv https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$ZEPHYR_SDK_VERSION/toolchain_linux-x86_64_arm-zephyr-eabi.tar.gz
+        wget -nv -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$ZEPHYR_SDK_VERSION/sha256.sum | shasum --check --ignore-missing
+        tar -xf toolchain_linux-x86_64_arm-zephyr-eabi.tar.gz -C zephyr-sdk
+
+    - name: Install Zephyr SDK (MIPS)
+      if: ${{ inputs.zephyr_toolchain == 'zephyr' && contains(inputs.zephyr_toolchain_arch, 'mips') }}
+      shell: sh
+      run: |
+        sudo apt install qemu qemu-system-mips
+        wget -nv https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$ZEPHYR_SDK_VERSION/toolchain_linux-x86_64_mips-zephyr-elf.tar.gz
+        wget -nv -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v$ZEPHYR_SDK_VERSION/sha256.sum | shasum --check --ignore-missing
+        tar -xf toolchain_linux-x86_64_mips-zephyr-elf.tar.gz -C zephyr-sdk
+
     - name: Run tests
       working-directory: tests
       shell: sh
diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml
index b4cd3968..79d30270 100644
--- a/.github/workflows/run-tests.yaml
+++ b/.github/workflows/run-tests.yaml
@@ -2,6 +2,9 @@ name: Run tests
 
 on: [pull_request]
 
+env:
+  ZEPHYR_SDK_VERSION: 0.15.0
+
 jobs:
   merge-test-win:
     runs-on: windows-latest
@@ -49,6 +52,7 @@ jobs:
       with:
         twister_arguments: "--platform ${{ matrix.platform }} ${{ matrix.asserts }}"
         zephyr_toolchain: ${{ matrix.platform == 'mps2_an521' && 'zephyr' || 'host'}}
+        zephyr_toolchain_arch: ${{ matrix.platform == 'mps2_an521' && 'arm' || ''}}
 
   merge-test-2:
     runs-on: ubuntu-latest
@@ -147,5 +151,6 @@ jobs:
     - name: Prepare and run tests
       uses: ./.github/actions/prepare_and_run_tests
       with:
-        twister_arguments: "--platform native_posix --platform native_posix_64 --platform mps2_an521 ${{ matrix.asserts }}"
+        twister_arguments: "--platform native_posix --platform native_posix_64 --platform mps2_an521 --platform qemu_malta_be ${{ matrix.asserts }}"
         zephyr_toolchain: zephyr
+        zephyr_toolchain_arch: arm,mips
diff --git a/tests/be_test.sh b/tests/be_test.sh
new file mode 100755
index 00000000..4b69e031
--- /dev/null
+++ b/tests/be_test.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Copyright (c) 2022 Nordic Semiconductor ASA
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+if [[ -z "$ZEHPYR_BASE" ]]; then
+        ZEPHYR_BASE=$(west topdir)/zephyr
+fi
+
+$ZEPHYR_BASE/scripts/twister -M -v -T . -W --platform qemu_malta_be $*
diff --git a/tests/cmake/test_template.cmake b/tests/cmake/test_template.cmake
index 2b703ff2..a5392197 100644
--- a/tests/cmake/test_template.cmake
+++ b/tests/cmake/test_template.cmake
@@ -15,6 +15,10 @@ if (CANONICAL)
   zephyr_compile_definitions(ZCBOR_CANONICAL)
 endif()
 
+if (CONFIG_BIG_ENDIAN OR BIG_ENDIAN)
+  zephyr_compile_definitions(ZCBOR_BIG_ENDIAN)
+endif()
+
 zephyr_compile_options(-Werror)
 
 if (CONFIG_64BIT)
diff --git a/tests/decode/test1_suit_old_formats/testcase.yaml b/tests/decode/test1_suit_old_formats/testcase.yaml
index bb92830d..7771f30a 100644
--- a/tests/decode/test1_suit_old_formats/testcase.yaml
+++ b/tests/decode/test1_suit_old_formats/testcase.yaml
@@ -1,4 +1,4 @@
 tests:
   zcbor.decode.test1_suit_old_formats:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode test1
diff --git a/tests/decode/test2_suit/testcase.yaml b/tests/decode/test2_suit/testcase.yaml
index 1aac1d21..2a5340be 100644
--- a/tests/decode/test2_suit/testcase.yaml
+++ b/tests/decode/test2_suit/testcase.yaml
@@ -1,4 +1,4 @@
 tests:
   zcbor.decode.test2_suit:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode test2
diff --git a/tests/decode/test3_simple/testcase.yaml b/tests/decode/test3_simple/testcase.yaml
index f59cb13c..e90f13df 100644
--- a/tests/decode/test3_simple/testcase.yaml
+++ b/tests/decode/test3_simple/testcase.yaml
@@ -1,4 +1,4 @@
 tests:
   zcbor.decode.test3_simple:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode test3
diff --git a/tests/decode/test5_corner_cases/testcase.yaml b/tests/decode/test5_corner_cases/testcase.yaml
index 2f08eb47..980c845c 100644
--- a/tests/decode/test5_corner_cases/testcase.yaml
+++ b/tests/decode/test5_corner_cases/testcase.yaml
@@ -1,8 +1,8 @@
 tests:
   zcbor.decode.test5_corner_cases:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode test5
   zcbor.decode.test5_corner_cases.indefinite_length_arrays:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode test5 indefinite
     extra_args: TEST_INDEFINITE_LENGTH_ARRAYS=1
diff --git a/tests/decode/test7_suit9_simple/testcase.yaml b/tests/decode/test7_suit9_simple/testcase.yaml
index 5d6196e2..7fc7f8ff 100644
--- a/tests/decode/test7_suit9_simple/testcase.yaml
+++ b/tests/decode/test7_suit9_simple/testcase.yaml
@@ -1,4 +1,4 @@
 tests:
   zcbor.decode.test7_suit9_simple:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode test7
diff --git a/tests/decode/test8_suit12/testcase.yaml b/tests/decode/test8_suit12/testcase.yaml
index c3038483..0c2166b0 100644
--- a/tests/decode/test8_suit12/testcase.yaml
+++ b/tests/decode/test8_suit12/testcase.yaml
@@ -1,4 +1,4 @@
 tests:
   zcbor.decode.test8_suit12:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode test8
diff --git a/tests/decode/test9_manifest14/testcase.yaml b/tests/decode/test9_manifest14/testcase.yaml
index 707592be..90f4af0c 100644
--- a/tests/decode/test9_manifest14/testcase.yaml
+++ b/tests/decode/test9_manifest14/testcase.yaml
@@ -1,8 +1,8 @@
 tests:
   zcbor.decode.test9_manifest14:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode manifest14 test9
   zcbor.cbor_decode.test9_manifest16:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor decode manifest16 test9
     extra_args: MANIFEST=manifest16
diff --git a/tests/encode/test1_suit/testcase.yaml b/tests/encode/test1_suit/testcase.yaml
index d590826d..8facf920 100644
--- a/tests/encode/test1_suit/testcase.yaml
+++ b/tests/encode/test1_suit/testcase.yaml
@@ -1,5 +1,5 @@
 tests:
   zcbor.encode.test1_suit.canonical:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor encode canonical test1
     extra_args: CANONICAL=CANONICAL
diff --git a/tests/encode/test2_simple/testcase.yaml b/tests/encode/test2_simple/testcase.yaml
index 9a2bf896..842b02ad 100644
--- a/tests/encode/test2_simple/testcase.yaml
+++ b/tests/encode/test2_simple/testcase.yaml
@@ -1,8 +1,8 @@
 tests:
   zcbor.encode.test2_simple:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor encode test
   zcbor.encode.test2_simple.canonical:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor encode canonical test
     extra_args: CANONICAL=CANONICAL
diff --git a/tests/encode/test3_corner_cases/testcase.yaml b/tests/encode/test3_corner_cases/testcase.yaml
index 63647074..a3ccebfa 100644
--- a/tests/encode/test3_corner_cases/testcase.yaml
+++ b/tests/encode/test3_corner_cases/testcase.yaml
@@ -1,8 +1,8 @@
 tests:
   zcbor.encode.test3_corner_cases:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor encode test3
   zcbor.encode.test3_corner_cases.canonical:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor encode canonical test3
     extra_args: CANONICAL=CANONICAL
diff --git a/tests/encode/test4_senml/testcase.yaml b/tests/encode/test4_senml/testcase.yaml
index 58babb5e..2755221a 100644
--- a/tests/encode/test4_senml/testcase.yaml
+++ b/tests/encode/test4_senml/testcase.yaml
@@ -1,8 +1,8 @@
 tests:
   zcbor.encode.test4_senml:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor encode test4
   zcbor.encode.test4_senml.canonical:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor encode canonical test4
     extra_args: CANONICAL=CANONICAL
diff --git a/tests/unit/test1_unit_tests/src/main.c b/tests/unit/test1_unit_tests/src/main.c
index 4253c75e..9392c5f8 100644
--- a/tests/unit/test1_unit_tests/src/main.c
+++ b/tests/unit/test1_unit_tests/src/main.c
@@ -804,6 +804,24 @@ void test_int(void)
 }
 
 
+/** This tests a regression in big-endian encoding, where small numbers (like 0)
+  * where handled incorrectly (1-off), because of an error in get_result().
+  */
+void test_encode_int_0(void)
+{
+	uint8_t payload1[100];
+	uint32_t values_32[2] = {0, UINT32_MAX};
+	uint64_t values_64[2] = {0, UINT64_MAX};
+	ZCBOR_STATE_E(state_e, 1, payload1, sizeof(payload1), 0);
+	ZCBOR_STATE_D(state_d, 1, payload1, sizeof(payload1), 16);
+
+	zassert_true(zcbor_uint32_put(state_e, values_32[0]));
+	zassert_true(zcbor_uint64_put(state_e, values_64[0]));
+	zassert_true(zcbor_uint32_expect(state_d, 0));
+	zassert_true(zcbor_uint64_expect(state_d, 0));
+}
+
+
 void test_main(void)
 {
 	ztest_test_suite(zcbor_unit_tests,
@@ -818,7 +836,8 @@ void test_main(void)
 			 ztest_unit_test(test_validate_fragments),
 			 ztest_unit_test(test_bstr_cbor_fragments),
 			 ztest_unit_test(test_canonical_list),
-			 ztest_unit_test(test_int)
+			 ztest_unit_test(test_int),
+			 ztest_unit_test(test_encode_int_0)
 	);
 	ztest_run_test_suite(zcbor_unit_tests);
 }
diff --git a/tests/unit/test1_unit_tests/testcase.yaml b/tests/unit/test1_unit_tests/testcase.yaml
index fe4b2def..6a2ec40b 100644
--- a/tests/unit/test1_unit_tests/testcase.yaml
+++ b/tests/unit/test1_unit_tests/testcase.yaml
@@ -1,4 +1,4 @@
 tests:
   zcbor.unit.test1:
-    platform_allow: native_posix native_posix_64 mps2_an521
+    platform_allow: native_posix native_posix_64 mps2_an521 qemu_malta_be
     tags: zcbor unit