diff --git a/.ci/check-style b/.ci/check-style index 977fdf221..16ad44390 100755 --- a/.ci/check-style +++ b/.ci/check-style @@ -8,7 +8,7 @@ set -e # Exit on pipe fail set -o pipefail -CLANGFORMAT=${CLANGFORMAT:-clang-format-15} +CLANGFORMAT=${CLANGFORMAT:-clang-format-18} command -v git >/dev/null 2>&1 || { echo >&2 "git is missing"; exit 1; } command -v xargs >/dev/null 2>&1 || { echo >&2 "xargs is missing"; exit 1; } diff --git a/.ci/check-tidy b/.ci/check-tidy index 789440428..38e8a1322 100755 --- a/.ci/check-tidy +++ b/.ci/check-tidy @@ -8,7 +8,7 @@ set -e # Exit on pipe fail set -o pipefail -CLANGTIDY=${CLANGTIDY:-clang-tidy-15} +CLANGTIDY=${CLANGTIDY:-clang-tidy-18} command -v git >/dev/null 2>&1 || { echo >&2 "git is missing"; exit 1; } command -v xargs >/dev/null 2>&1 || { echo >&2 "xargs is missing"; exit 1; } diff --git a/.ci/run-container-ci b/.ci/run-container-ci index a35332861..996013669 100755 --- a/.ci/run-container-ci +++ b/.ci/run-container-ci @@ -25,7 +25,7 @@ set -e set -x -CONTAINER=shiftcrypto/firmware_v2:37 +CONTAINER=shiftcrypto/firmware_v2:38 if [ "$1" == "pull" ] ; then docker pull "$CONTAINER" diff --git a/Dockerfile b/Dockerfile index 5ce3b9676..09ee291e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,8 +20,8 @@ ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && apt-get upgrade -y && apt-get install -y wget nano rsync curl gnupg2 jq unzip bzip2 # for clang-*-15, see https://apt.llvm.org/ -RUN echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" >> /etc/apt/sources.list && \ - echo "deb-src http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" >> /etc/apt/sources.list && \ +RUN echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" >> /etc/apt/sources.list && \ + echo "deb-src http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" >> /etc/apt/sources.list && \ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - # Install gcc8-arm-none-eabi @@ -37,7 +37,7 @@ RUN mkdir ~/Downloads &&\ # Tools for building RUN apt-get update && apt-get install -y \ build-essential \ - llvm-15 \ + llvm-18 \ gcc-10 \ binutils \ valgrind \ @@ -68,8 +68,8 @@ RUN update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-10 100 RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ - clang-format-15 \ - clang-tidy-15 + clang-format-18 \ + clang-tidy-18 RUN python3 -m pip install --upgrade pip diff --git a/scripts/format b/scripts/format index 82b4f3f36..c88da3444 100755 --- a/scripts/format +++ b/scripts/format @@ -8,7 +8,7 @@ set -e # Exit on pipe fail set -o pipefail -CLANGFORMAT=${CLANGFORMAT:-clang-format-15} +CLANGFORMAT=${CLANGFORMAT:-clang-format-18} CLANGFORMAT_FLAGS=${CLANGFORMAT_FLAGS:--i} VERBOSE=${VERBOSE:-NO} diff --git a/src/factorysetup.c b/src/factorysetup.c index 3ae599d40..a112e4b3f 100644 --- a/src/factorysetup.c +++ b/src/factorysetup.c @@ -343,6 +343,5 @@ int main(void) } } - while (1) - ; + while (1); } diff --git a/src/memory/nvmctrl.c b/src/memory/nvmctrl.c index 4965f5853..937c8f1ce 100644 --- a/src/memory/nvmctrl.c +++ b/src/memory/nvmctrl.c @@ -19,10 +19,8 @@ void nvmctrl_exec_cmd(uint16_t cmd) { /* Wait until the NVM is ready to accept a new command. */ - while (NVMCTRL->STATUS.bit.READY == 0) - ; + while (NVMCTRL->STATUS.bit.READY == 0); NVMCTRL->ADDR.reg = (uint32_t)NVMCTRL_USER; NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | cmd; - while (NVMCTRL->STATUS.bit.READY == 0) - ; + while (NVMCTRL->STATUS.bit.READY == 0); } diff --git a/src/memory/smarteeprom.c b/src/memory/smarteeprom.c index fea579d91..03a67ce2c 100644 --- a/src/memory/smarteeprom.c +++ b/src/memory/smarteeprom.c @@ -48,10 +48,8 @@ void smarteeprom_disable(void) nvmctrl_exec_cmd(NVMCTRL_CTRLB_CMD_PBC); // Clear page buffer *((uint32_t*)NVMCTRL_FUSES_SEEPSZ_ADDR) = config_word; nvmctrl_exec_cmd(NVMCTRL_CTRLB_CMD_WQW); // Write a 128-bit word - while (!NVMCTRL->STATUS.bit.READY) - ; - while (NVMCTRL->SEESTAT.bit.BUSY) - ; + while (!NVMCTRL->STATUS.bit.READY); + while (NVMCTRL->SEESTAT.bit.BUSY); } void smarteeprom_setup(void) @@ -88,10 +86,8 @@ void smarteeprom_setup(void) nvmctrl_exec_cmd(NVMCTRL_CTRLB_CMD_PBC); // Clear page buffer *((uint32_t*)NVMCTRL_FUSES_SEEPSZ_ADDR) = config_word; nvmctrl_exec_cmd(NVMCTRL_CTRLB_CMD_WQW); // Write a 128-bit word - while (!NVMCTRL->STATUS.bit.READY) - ; - while (NVMCTRL->SEESTAT.bit.BUSY) - ; + while (!NVMCTRL->STATUS.bit.READY); + while (NVMCTRL->SEESTAT.bit.BUSY); } void smarteeprom_bb02_config(void) @@ -122,8 +118,7 @@ void smarteeprom_read(size_t address, size_t bytes, uint8_t* out_buffer) } volatile uint8_t* eeprom = (uint8_t*)SEEPROM_ADDR + address; - while (NVMCTRL->SEESTAT.bit.BUSY) - ; + while (NVMCTRL->SEESTAT.bit.BUSY); for (size_t i = 0; i < bytes; ++i) { out_buffer[i] = *eeprom; eeprom++; @@ -136,8 +131,7 @@ void smarteeprom_write(size_t address, size_t bytes, const uint8_t* buffer) Abort("NULL input buffer in smarteeprom_write."); } volatile uint8_t* eeprom = (uint8_t*)SEEPROM_ADDR + address; - while (NVMCTRL->SEESTAT.bit.BUSY) - ; + while (NVMCTRL->SEESTAT.bit.BUSY); /* * Buffered write of multiple bytes. * Note that crossing a 32B page will still result in a partial flush @@ -149,10 +143,8 @@ void smarteeprom_write(size_t address, size_t bytes, const uint8_t* buffer) } /* Now, flush the write we have issued. */ nvmctrl_exec_cmd(NVMCTRL_CTRLB_CMD_SEEFLUSH); - while (NVMCTRL->SEESTAT.bit.LOAD != 0) - ; - while (NVMCTRL->SEESTAT.bit.BUSY != 0) - ; + while (NVMCTRL->SEESTAT.bit.LOAD != 0); + while (NVMCTRL->SEESTAT.bit.BUSY != 0); /* * Read back the buffer. * Check that it matches what we've just written. diff --git a/src/pukcc/pukcc.c b/src/pukcc/pukcc.c index 44db2571f..141183a36 100644 --- a/src/pukcc/pukcc.c +++ b/src/pukcc/pukcc.c @@ -177,19 +177,14 @@ static void pukcc_self_test(void) { static bool self_test_run = false; if (!self_test_run) { - while ((PUKCCSR & BIT_PUKCCSR_CLRRAM_BUSY) != 0) - ; + while ((PUKCCSR & BIT_PUKCCSR_CLRRAM_BUSY) != 0); memset(&PUKCLParam, 0, sizeof(PUKCL_PARAM)); pvPUKCLParam = &PUKCLParam; vPUKCL_Process(SelfTest, pvPUKCLParam); - while (PUKCL(u2Status) != PUKCL_OK) - ; - while (pvPUKCLParam->P.PUKCL_SelfTest.u4Version != PUKCL_VERSION) - ; - while (pvPUKCLParam->P.PUKCL_SelfTest.u4CheckNum1 != 0x6E70DDD2) - ; - while (pvPUKCLParam->P.PUKCL_SelfTest.u4CheckNum2 != 0x25C8D64F) - ; + while (PUKCL(u2Status) != PUKCL_OK); + while (pvPUKCLParam->P.PUKCL_SelfTest.u4Version != PUKCL_VERSION); + while (pvPUKCLParam->P.PUKCL_SelfTest.u4CheckNum1 != 0x6E70DDD2); + while (pvPUKCLParam->P.PUKCL_SelfTest.u4CheckNum2 != 0x25C8D64F); self_test_run = true; } } diff --git a/src/qtouch/qtouch.c b/src/qtouch/qtouch.c index 6fa2e68dd..e550ca91b 100644 --- a/src/qtouch/qtouch.c +++ b/src/qtouch/qtouch.c @@ -174,35 +174,17 @@ qtm_touch_key_control_t qtlib_key_set1 = { /**********************************************************/ /**************** Binding Layer Module ******************/ /**********************************************************/ -#define LIB_MODULES_INIT_LIST \ - { \ - (module_init_t) & qtm_ptc_init_acquisition_module, null \ - } +#define LIB_MODULES_INIT_LIST {(module_init_t) & qtm_ptc_init_acquisition_module, null} -#define LIB_MODULES_PROC_LIST \ - { \ - (module_proc_t) & qtm_key_sensors_process, null \ - } +#define LIB_MODULES_PROC_LIST {(module_proc_t) & qtm_key_sensors_process, null} -#define LIB_INIT_DATA_MODELS_LIST \ - { \ - (void*)&qtlib_acq_set1, null \ - } +#define LIB_INIT_DATA_MODELS_LIST {(void*)&qtlib_acq_set1, null} -#define LIB_DATA_MODELS_PROC_LIST \ - { \ - (void*)&qtlib_key_set1, null \ - } +#define LIB_DATA_MODELS_PROC_LIST {(void*)&qtlib_key_set1, null} -#define LIB_MODULES_ACQ_ENGINES_LIST \ - { \ - (module_acq_t) & qtm_ptc_start_measurement_seq, null \ - } +#define LIB_MODULES_ACQ_ENGINES_LIST {(module_acq_t) & qtm_ptc_start_measurement_seq, null} -#define LIB_MODULES_ACQ_ENGINES_LIST_DM \ - { \ - (void*)&qtlib_acq_set1, null \ - } +#define LIB_MODULES_ACQ_ENGINES_LIST_DM {(void*)&qtlib_acq_set1, null} /* QTM run time options */ module_init_t library_modules_init[] = LIB_MODULES_INIT_LIST; diff --git a/src/qtouch/qtouch.h b/src/qtouch/qtouch.h index 31601d608..f119d06b0 100644 --- a/src/qtouch/qtouch.h +++ b/src/qtouch/qtouch.h @@ -86,47 +86,63 @@ extern "C" { * Gain , Digital Gain), filter level} */ // Slider 1 buttons -#define NODE_0_PARAMS \ - { \ - X_NONE, Y_LINE(26), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } -#define NODE_1_PARAMS \ - { \ - X_NONE, Y_LINE(27), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } -#define NODE_2_PARAMS \ - { \ - X_NONE, Y_LINE(28), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } -#define NODE_3_PARAMS \ - { \ - X_NONE, Y_LINE(29), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } +#define NODE_0_PARAMS \ + {X_NONE, \ + Y_LINE(26), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} +#define NODE_1_PARAMS \ + {X_NONE, \ + Y_LINE(27), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} +#define NODE_2_PARAMS \ + {X_NONE, \ + Y_LINE(28), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} +#define NODE_3_PARAMS \ + {X_NONE, \ + Y_LINE(29), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} // Slider 0 buttons -#define NODE_4_PARAMS \ - { \ - X_NONE, Y_LINE(30), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } -#define NODE_5_PARAMS \ - { \ - X_NONE, Y_LINE(31), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } -#define NODE_6_PARAMS \ - { \ - X_NONE, Y_LINE(20), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } -#define NODE_7_PARAMS \ - { \ - X_NONE, Y_LINE(21), 0, NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), FILTER_LEVEL_512 \ - } +#define NODE_4_PARAMS \ + {X_NONE, \ + Y_LINE(30), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} +#define NODE_5_PARAMS \ + {X_NONE, \ + Y_LINE(31), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} +#define NODE_6_PARAMS \ + {X_NONE, \ + Y_LINE(20), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} +#define NODE_7_PARAMS \ + {X_NONE, \ + Y_LINE(21), \ + 0, \ + NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ + NODE_GAIN(GAIN_4, GAIN_4), \ + FILTER_LEVEL_512} /**********************************************************/ /***************** Key Params ******************/ @@ -141,38 +157,14 @@ extern "C" { * {Sensor Threshold, Sensor Hysterisis, Sensor AKS} */ // 0..3 higher Slider left to right 4..7 lower Slider right to left -#define KEY_0_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } -#define KEY_1_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } -#define KEY_2_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } -#define KEY_3_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } -#define KEY_4_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } -#define KEY_5_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } -#define KEY_6_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } -#define KEY_7_PARAMS \ - { \ - 16, HYST_50, NO_AKS_GROUP \ - } +#define KEY_0_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_1_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_2_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_3_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_4_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_5_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_6_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_7_PARAMS {16, HYST_50, NO_AKS_GROUP} /* De-bounce counter for additional measurements to confirm touch detection * Range: 0 to 255. diff --git a/src/rust/bitbox02-rust-c/src/workflow.rs b/src/rust/bitbox02-rust-c/src/workflow.rs index 2bde948df..1a3591934 100644 --- a/src/rust/bitbox02-rust-c/src/workflow.rs +++ b/src/rust/bitbox02-rust-c/src/workflow.rs @@ -100,8 +100,8 @@ pub unsafe extern "C" fn rust_workflow_unlock_poll(result_out: &mut bool) -> boo /// Returns true if there was a result. #[no_mangle] pub unsafe extern "C" fn rust_workflow_confirm_poll(result_out: &mut bool) -> bool { - match &CONFIRM_STATE { - TaskState::ResultAvailable(result) => { + match CONFIRM_STATE { + TaskState::ResultAvailable(ref result) => { CONFIRM_TITLE = None; CONFIRM_BODY = None; CONFIRM_PARAMS = None; diff --git a/src/rust/bitbox02-rust/src/hww/api/ethereum/sign_typed_msg.rs b/src/rust/bitbox02-rust/src/hww/api/ethereum/sign_typed_msg.rs index f182723d6..7f732ce9c 100644 --- a/src/rust/bitbox02-rust/src/hww/api/ethereum/sign_typed_msg.rs +++ b/src/rust/bitbox02-rust/src/hww/api/ethereum/sign_typed_msg.rs @@ -423,7 +423,10 @@ async fn hash_struct( child_formatted_path.push("".into()); for (index, member) in typ.members.iter().enumerate() { *child_path.last_mut().unwrap() = index as u32; - *child_formatted_path.last_mut().unwrap() = member.name.clone(); + child_formatted_path + .last_mut() + .unwrap() + .clone_from(&member.name); let member_type = member.r#type.as_ref().ok_or(Error::InvalidInput)?; encode_member( &mut hasher, diff --git a/src/rust/rust-toolchain b/src/rust/rust-toolchain index 32a6ce3c7..54227249d 100644 --- a/src/rust/rust-toolchain +++ b/src/rust/rust-toolchain @@ -1 +1 @@ -1.76.0 +1.78.0 diff --git a/src/ui/oled/sh1107.c b/src/ui/oled/sh1107.c index b4dc97d26..de2da7591 100644 --- a/src/ui/oled/sh1107.c +++ b/src/ui/oled/sh1107.c @@ -16,7 +16,7 @@ #include "oled_writer.h" // Specify the column address of display RAM 0-127 -#define SH1107_CMD_SET_LOW_COL(column) (0x00 | ((column)&0x0F)) +#define SH1107_CMD_SET_LOW_COL(column) (0x00 | ((column) & 0x0F)) #define SH1107_CMD_SET_HIGH_COL(column) (0x10 | (((column) >> 4) & 0x07)) // In page adressing mode, after the display RAM is written to, the column address is @@ -55,7 +55,7 @@ #define SH1107_CMD_SET_DISPLAY_ON 0xAF #define SH1107_CMD_SET_DISPLAY_OFF 0xAE -#define SH1107_CMD_SET_PAGE_START_ADDRESS(page) (0xB0 | ((page)&0x0f)) +#define SH1107_CMD_SET_PAGE_START_ADDRESS(page) (0xB0 | ((page) & 0x0f)) #define SH1107_CMD_SET_COM_OUTPUT_SCAN_UP 0xC0 #define SH1107_CMD_SET_COM_OUTPUT_SCAN_DOWN 0xC8 diff --git a/src/ui/oled/ssd1312.c b/src/ui/oled/ssd1312.c index 997fb182a..f92317d55 100644 --- a/src/ui/oled/ssd1312.c +++ b/src/ui/oled/ssd1312.c @@ -16,7 +16,7 @@ #include "oled_writer.h" #include -#define SSD1312_CMD_SET_LOW_COL(column) (0x00 | ((column)&0x0F)) +#define SSD1312_CMD_SET_LOW_COL(column) (0x00 | ((column) & 0x0F)) #define SSD1312_CMD_SET_HIGH_COL(column) (0x10 | (((column) >> 4) & 0x07)) // Double byte ecommand @@ -32,7 +32,7 @@ #define SSD1312_CMD_SET_PAGE_ADDRESS 0x22 // Specify column address to determine the initial line (0-63) -#define SSD1312_CMD_SET_DISPLAY_START_LINE(reg) (0x40 | ((reg)&0x3f)) +#define SSD1312_CMD_SET_DISPLAY_START_LINE(reg) (0x40 | ((reg) & 0x3f)) // Double byte command (0x01-0xff) #define SSD1312_CMD_SET_CONTRAST_CONTROL 0x81 @@ -55,7 +55,7 @@ #define SSD1312_CMD_SET_DISPLAY_ON 0xAF #define SSD1312_CMD_SET_DISPLAY_OFF 0xAE -#define SSD1312_CMD_SET_PAGE_START_ADDRESS(page) (0xB0 | ((page)&0x07)) +#define SSD1312_CMD_SET_PAGE_START_ADDRESS(page) (0xB0 | ((page) & 0x07)) #define SSD1312_CMD_SET_COM_OUTPUT_SCAN_UP 0xC0 #define SSD1312_CMD_SET_COM_OUTPUT_SCAN_DOWN 0xC8 diff --git a/src/util.h b/src/util.h index fa5cf3890..f1aafa08c 100644 --- a/src/util.h +++ b/src/util.h @@ -43,7 +43,7 @@ #define strlens(s) ((s) == NULL ? 0 : strlen(s)) #define STREQ(a, b) (strcmp((a), (b)) == 0) #define MEMEQ(a, b, c) (memcmp((a), (b), (c)) == 0) -#define SIGMOID(a) (0.0018F * (a)*abs(a) / (1 + 0.002F * (a) * (a))); +#define SIGMOID(a) (0.0018F * (a) * abs(a) / (1 + 0.002F * (a) * (a))); // We define our own true false which are more secure than stdbool true/false becuase it requires // flipping many more bits. diff --git a/test/unit-test/u2f/sha2.c b/test/unit-test/u2f/sha2.c index 341f664e4..3263eecba 100644 --- a/test/unit-test/u2f/sha2.c +++ b/test/unit-test/u2f/sha2.c @@ -137,8 +137,7 @@ typedef uint64_t sha2_word64; /* Exactly 8 bytes */ static volatile void* MEMSET_BZERO(volatile void* dst, size_t len) { volatile char* buf; - for (buf = (volatile char*)dst; len; buf[--len] = 0) - ; + for (buf = (volatile char*)dst; len; buf[--len] = 0); return dst; }