On 20/09/16 17:49, Kyrill Tkachov wrote: > > On 20/09/16 15:13, Richard Earnshaw (lists) wrote: >> On 08/09/16 12:00, Kyrill Tkachov wrote: >>> Hi all, >>> >>> This is a rebase and slight respin of [1] that I sent out last November >>> to change all uses of >>> sprintf to snprintf in the arm backend. >>> >>> Bootstrapped and tested on arm-none-linux-gnueabihf. >>> Ok for trunk? >>> >>> Thanks, >>> Kyrill >>> >>> [1] https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00937.html >>> >>> 2016-09-08 Kyrylo Tkachov <kyrylo.tkac...@arm.com> >>> >>> * config/arm/arm.c (arm_set_fixed_optab_libfunc): Use snprintf >>> rather than sprintf. >>> (arm_set_fixed_conv_libfunc): Likewise. >>> (arm_option_override): Likewise. >>> (neon_output_logic_immediate): Likewise. >>> (neon_output_shift_immediate): Likewise. >>> (arm_output_multireg_pop): Likewise. >>> (vfp_output_vstmd): Likewise. >>> (output_move_vfp): Likewise. >>> (output_move_neon): Likewise. >>> (output_return_instruction): Likewise. >>> (arm_elf_asm_cdtor): Likewise. >>> (arm_output_shift): Likewise. >>> (arm_output_iwmmxt_shift_immediate): Likewise. >>> (arm_output_iwmmxt_tinsr): Likewise. >>> * config/arm/neon.md (*neon_mov<mode>, VDX): Likewise. >>> (*neon_mov<mode>, VQXMOV): Likewise. >>> (neon_vc<cmp_op><mode>_insn): Likewise. >>> (neon_vc<cmp_op_unsp><mode>_insn_unspec): Likewise. >> Most of these should assert that truncation did not occur (it's an >> internal error if the buffers aren't large enough). In a few cases we >> should call output_operand_lossage on failure since it might be due to a >> user writing inline assembly and overflowing a buffer. >> >> I don't think we should silently accept a truncated write. > > Ok, I'm proposing a new function defined in system.h > (though I'm open to suggestions for other location). > It would be something like: > > static inline int ATTRIBUTE_PRINTF_3 > gcc_snprintf (char *str, size_t size, const char *format, ...) > { > va_list ap; > va_start(ap, format); > size_t res = vsnprintf (str, size, format, ap); > va_end (ap); > /* vsnprintf returns >= size if input was truncated. */ > gcc_assert (res < size); > return res; > } > > Would that be acceptable? >
Yes, that's sort of what I had in mind. Not sure if it needs to be inline, though; *printf are not generally performance-critical functions and this bloats code somewhat with two function calls for each invocation. R. > Thanks, > Kyrill > >> >> R. >> >>> arm-snprintf.patch >>> >>> >>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c >>> index >>> 946f308ca84e232af8af6eca4813464914cbd59c..8ff6c0e18f7c2a2eed72e56402ed582c9f692d2d >>> 100644 >>> --- a/gcc/config/arm/arm.c >>> +++ b/gcc/config/arm/arm.c >>> @@ -2388,9 +2388,10 @@ arm_set_fixed_optab_libfunc (optab optable, >>> machine_mode mode, >>> char buffer[50]; >>> if (num_suffix == 0) >>> - sprintf (buffer, "__gnu_%s%s", funcname, modename); >>> + snprintf (buffer, sizeof (buffer), "__gnu_%s%s", funcname, >>> modename); >>> else >>> - sprintf (buffer, "__gnu_%s%s%d", funcname, modename, num_suffix); >>> + snprintf (buffer, sizeof (buffer), "__gnu_%s%s%d", funcname, >>> + modename, num_suffix); >>> set_optab_libfunc (optable, mode, buffer); >>> } >>> @@ -2409,8 +2410,8 @@ arm_set_fixed_conv_libfunc (convert_optab >>> optable, machine_mode to, >>> && ALL_FRACT_MODE_P (from) == ALL_FRACT_MODE_P (to)) >>> maybe_suffix_2 = "2"; >>> - sprintf (buffer, "__gnu_%s%s%s%s", funcname, fromname, toname, >>> - maybe_suffix_2); >>> + snprintf (buffer, sizeof (buffer), "__gnu_%s%s%s%s", funcname, >>> + fromname, toname, maybe_suffix_2); >>> set_conv_libfunc (optable, to, from, buffer); >>> } >>> @@ -3163,7 +3164,8 @@ arm_option_override (void) >>> if (!arm_selected_tune) >>> arm_selected_tune = &all_cores[arm_selected_cpu->core]; >>> - sprintf (arm_arch_name, "__ARM_ARCH_%s__", arm_selected_cpu->arch); >>> + snprintf (arm_arch_name, sizeof (arm_arch_name), >>> + "__ARM_ARCH_%s__", arm_selected_cpu->arch); >>> insn_flags = arm_selected_cpu->flags; >>> arm_base_arch = arm_selected_cpu->base_arch; >>> @@ -12735,9 +12737,11 @@ neon_output_logic_immediate (const char >>> *mnem, rtx *op2, machine_mode mode, >>> gcc_assert (is_valid != 0); >>> if (quad) >>> - sprintf (templ, "%s.i%d\t%%q0, %%2", mnem, width); >>> + snprintf (templ, sizeof (templ), "%s.i%d\t%%q0, %%2", >>> + mnem, width); >>> else >>> - sprintf (templ, "%s.i%d\t%%P0, %%2", mnem, width); >>> + snprintf (templ, sizeof (templ), "%s.i%d\t%%P0, %%2", >>> + mnem, width); >>> return templ; >>> } >>> @@ -12757,9 +12761,11 @@ neon_output_shift_immediate (const char >>> *mnem, char sign, rtx *op2, >>> gcc_assert (is_valid != 0); >>> if (quad) >>> - sprintf (templ, "%s.%c%d\t%%q0, %%q1, %%2", mnem, sign, width); >>> + snprintf (templ, sizeof (templ), >>> + "%s.%c%d\t%%q0, %%q1, %%2", mnem, sign, width); >>> else >>> - sprintf (templ, "%s.%c%d\t%%P0, %%P1, %%2", mnem, sign, width); >>> + snprintf (templ, sizeof (templ), >>> + "%s.%c%d\t%%P0, %%P1, %%2", mnem, sign, width); >>> return templ; >>> } >>> @@ -17858,17 +17864,17 @@ arm_output_multireg_pop (rtx *operands, >>> bool return_pc, rtx cond, bool reverse, >>> conditional = reverse ? "%?%D0" : "%?%d0"; >>> /* Can't use POP if returning from an interrupt. */ >>> if ((regno_base == SP_REGNUM) && update && !(interrupt_p && >>> return_pc)) >>> - sprintf (pattern, "pop%s\t{", conditional); >>> + snprintf (pattern, sizeof (pattern), "pop%s\t{", conditional); >>> else >>> { >>> /* Output ldmfd when the base register is SP, otherwise >>> output ldmia. >>> It's just a convention, their semantics are identical. */ >>> if (regno_base == SP_REGNUM) >>> - sprintf (pattern, "ldmfd%s\t", conditional); >>> + snprintf (pattern, sizeof (pattern), "ldmfd%s\t", conditional); >>> else if (update) >>> - sprintf (pattern, "ldmia%s\t", conditional); >>> + snprintf (pattern, sizeof (pattern), "ldmia%s\t", conditional); >>> else >>> - sprintf (pattern, "ldm%s\t", conditional); >>> + snprintf (pattern, sizeof (pattern), "ldm%s\t", conditional); >>> strcat (pattern, reg_names[regno_base]); >>> if (update) >>> @@ -17924,7 +17930,8 @@ vfp_output_vstmd (rtx * operands) >>> base = (REGNO (operands[1]) - FIRST_VFP_REGNUM) / 2; >>> for (i = 1; i < XVECLEN (operands[2], 0); i++) >>> { >>> - p += sprintf (&pattern[p], ", d%d", base + i); >>> + p += snprintf (&pattern[p], sizeof (pattern), >>> + ", d%d", base + i); >>> } >>> strcpy (&pattern[p], "}"); >>> @@ -18719,7 +18726,7 @@ output_move_vfp (rtx *operands) >>> break; >>> } >>> - sprintf (buff, templ, >>> + snprintf (buff, sizeof (buff), templ, >>> load ? "ld" : "st", >>> dp ? "64" : "32", >>> dp ? "P" : "", >>> @@ -18859,7 +18866,8 @@ output_move_neon (rtx *operands) >>> } >>> else >>> { >>> - sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" : "st"); >>> + snprintf (buff, sizeof (buff), >>> + "v%sr%%?\t%%P0, %%1", load ? "ld" : "st"); >>> output_asm_insn (buff, ops); >>> } >>> } >>> @@ -18867,7 +18875,8 @@ output_move_neon (rtx *operands) >>> { >>> ops[0] = gen_rtx_REG (DImode, REGNO (reg) + 2 * overlap); >>> ops[1] = adjust_address (mem, SImode, 8 * overlap); >>> - sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" : "st"); >>> + snprintf (buff, sizeof (buff), >>> + "v%sr%%?\t%%P0, %%1", load ? "ld" : "st"); >>> output_asm_insn (buff, ops); >>> } >>> @@ -18878,7 +18887,7 @@ output_move_neon (rtx *operands) >>> gcc_unreachable (); >>> } >>> - sprintf (buff, templ, load ? "ld" : "st"); >>> + snprintf (buff, sizeof (buff), templ, load ? "ld" : "st"); >>> output_asm_insn (buff, ops); >>> return ""; >>> @@ -19606,7 +19615,8 @@ output_return_instruction (rtx operand, bool >>> really_return, bool reverse, >>> gcc_assert (!cfun->calls_alloca || really_return); >>> - sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd'); >>> + snprintf (conditional, sizeof (conditional), >>> + "%%?%%%c0", reverse ? 'D' : 'd'); >>> cfun->machine->return_used_this_function = 1; >>> @@ -19657,7 +19667,8 @@ output_return_instruction (rtx operand, >>> bool really_return, bool reverse, >>> || ! really_return >>> || ! IS_INTERRUPT (func_type))) >>> { >>> - sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional, >>> + snprintf (instr, sizeof (instr), >>> + "ldr%s\t%%|%s, [%%|sp], #4", conditional, >>> (reg == LR_REGNUM) ? return_reg : reg_names[reg]); >>> } >>> else >>> @@ -19677,7 +19688,8 @@ output_return_instruction (rtx operand, bool >>> really_return, bool reverse, >>> gcc_assert (stack_adjust == 0 || stack_adjust == 4); >>> if (stack_adjust && arm_arch5 && TARGET_ARM) >>> - sprintf (instr, "ldmib%s\t%%|sp, {", conditional); >>> + snprintf (instr, sizeof (instr), "ldmib%s\t%%|sp, {", >>> + conditional); >>> else >>> { >>> /* If we can't use ldmib (SA110 bug), >>> @@ -19685,17 +19697,20 @@ output_return_instruction (rtx operand, >>> bool really_return, bool reverse, >>> if (stack_adjust) >>> live_regs_mask |= 1 << 3; >>> - sprintf (instr, "ldmfd%s\t%%|sp, {", conditional); >>> + snprintf (instr, sizeof (instr), "ldmfd%s\t%%|sp, {", >>> + conditional); >>> } >>> } >>> /* For interrupt returns we have to use an LDM rather than >>> a POP so that we can use the exception return variant. */ >>> else if (IS_INTERRUPT (func_type)) >>> - sprintf (instr, "ldmfd%s\t%%|sp!, {", conditional); >>> + snprintf (instr, sizeof (instr), "ldmfd%s\t%%|sp!, {", >>> conditional); >>> else >>> - sprintf (instr, "pop%s\t{", conditional); >>> + snprintf (instr, sizeof (instr), "pop%s\t{", conditional); >>> - p = instr + strlen (instr); >>> + size_t len = strlen (instr); >>> + p = instr + len; >>> + size_t rem_size = sizeof (instr) - len; >>> for (reg = 0; reg <= SP_REGNUM; reg++) >>> if (live_regs_mask & (1 << reg)) >>> @@ -19717,7 +19732,7 @@ output_return_instruction (rtx operand, bool >>> really_return, bool reverse, >>> if (live_regs_mask & (1 << LR_REGNUM)) >>> { >>> - sprintf (p, "%s%%|%s}", first ? "" : ", ", return_reg); >>> + snprintf (p, rem_size, "%s%%|%s}", first ? "" : ", ", >>> return_reg); >>> /* If returning from an interrupt, restore the CPSR. */ >>> if (IS_INTERRUPT (func_type)) >>> strcat (p, "^"); >>> @@ -19747,25 +19762,27 @@ output_return_instruction (rtx operand, >>> bool really_return, bool reverse, >>> case ARM_FT_ISR: >>> case ARM_FT_FIQ: >>> /* ??? This is wrong for unified assembly syntax. */ >>> - sprintf (instr, "sub%ss\t%%|pc, %%|lr, #4", conditional); >>> + snprintf (instr, sizeof (instr), "sub%ss\t%%|pc, %%|lr, #4", >>> + conditional); >>> break; >>> case ARM_FT_INTERWORKED: >>> - gcc_assert (arm_arch5 || arm_arch4t); >>> - sprintf (instr, "bx%s\t%%|lr", conditional); >>> + snprintf (instr, sizeof (instr), "bx%s\t%%|lr", conditional); >>> break; >>> case ARM_FT_EXCEPTION: >>> /* ??? This is wrong for unified assembly syntax. */ >>> - sprintf (instr, "mov%ss\t%%|pc, %%|lr", conditional); >>> + snprintf (instr, sizeof (instr), "mov%ss\t%%|pc, %%|lr", >>> + conditional); >>> break; >>> default: >>> /* Use bx if it's available. */ >>> if (arm_arch5 || arm_arch4t) >>> - sprintf (instr, "bx%s\t%%|lr", conditional); >>> + snprintf (instr, sizeof (instr), "bx%s\t%%|lr", conditional); >>> else >>> - sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional); >>> + snprintf (instr, sizeof (instr), "mov%s\t%%|pc, %%|lr", >>> + conditional); >>> break; >>> } >>> @@ -22817,9 +22834,9 @@ arm_elf_asm_cdtor (rtx symbol, int >>> priority, bool is_ctor) >>> if (priority != DEFAULT_INIT_PRIORITY) >>> { >>> char buf[18]; >>> - sprintf (buf, "%s.%.5u", >>> - is_ctor ? ".init_array" : ".fini_array", >>> - priority); >>> + snprintf (buf, sizeof (buf), "%s.%.5u", >>> + is_ctor ? ".init_array" : ".fini_array", >>> + priority); >>> s = get_section (buf, SECTION_WRITE, NULL_TREE); >>> } >>> else if (is_ctor) >>> @@ -27429,10 +27446,10 @@ arm_output_shift(rtx * operands, int >>> set_flags) >>> { >>> if (val != -1) >>> operands[2] = GEN_INT(val); >>> - sprintf (pattern, "%s%%%c\t%%0, %%1, %%2", shift, c); >>> + snprintf (pattern, sizeof (pattern), "%s%%%c\t%%0, %%1, %%2", >>> shift, c); >>> } >>> else >>> - sprintf (pattern, "mov%%%c\t%%0, %%1", c); >>> + snprintf (pattern, sizeof (pattern), "mov%%%c\t%%0, %%1", c); >>> output_asm_insn (pattern, operands); >>> return ""; >>> @@ -27456,33 +27473,35 @@ arm_output_iwmmxt_shift_immediate (const >>> char *insn_name, rtx *operands, bool wr >>> { >>> if (wror_or_wsra) >>> { >>> - sprintf (templ, "%s\t%%0, %%1, #%d", insn_name, 32); >>> - output_asm_insn (templ, operands); >>> - if (opmode == DImode) >>> - { >>> - sprintf (templ, "%s\t%%0, %%0, #%d", insn_name, 32); >>> + snprintf (templ, sizeof (templ), "%s\t%%0, %%1, #%d", insn_name, >>> 32); >>> + output_asm_insn (templ, operands); >>> + if (opmode == DImode) >>> + { >>> + snprintf (templ, sizeof (templ), "%s\t%%0, %%0, #%d", >>> + insn_name, 32); >>> output_asm_insn (templ, operands); >>> - } >>> + } >>> } >>> else >>> { >>> - /* The destination register will contain all zeros. */ >>> - sprintf (templ, "wzero\t%%0"); >>> - output_asm_insn (templ, operands); >>> + /* The destination register will contain all zeros. */ >>> + snprintf (templ, sizeof (templ), "wzero\t%%0"); >>> + output_asm_insn (templ, operands); >>> } >>> return ""; >>> } >>> if ((opmode == DImode) && (shift > 32)) >>> { >>> - sprintf (templ, "%s\t%%0, %%1, #%d", insn_name, 32); >>> + snprintf (templ, sizeof (templ), "%s\t%%0, %%1, #%d", >>> insn_name, 32); >>> output_asm_insn (templ, operands); >>> - sprintf (templ, "%s\t%%0, %%0, #%d", insn_name, shift - 32); >>> + snprintf (templ, sizeof (templ), "%s\t%%0, %%0, #%d", >>> + insn_name, shift - 32); >>> output_asm_insn (templ, operands); >>> } >>> else >>> { >>> - sprintf (templ, "%s\t%%0, %%1, #%d", insn_name, shift); >>> + snprintf (templ, sizeof (templ), "%s\t%%0, %%1, #%d", >>> insn_name, shift); >>> output_asm_insn (templ, operands); >>> } >>> return ""; >>> @@ -27510,13 +27529,13 @@ arm_output_iwmmxt_tinsr (rtx *operands) >>> switch (GET_MODE (operands[0])) >>> { >>> case V8QImode: >>> - sprintf (templ, "tinsrb%%?\t%%0, %%2, #%d", i); >>> + snprintf (templ, sizeof (templ), "tinsrb%%?\t%%0, %%2, #%d", i); >>> break; >>> case V4HImode: >>> - sprintf (templ, "tinsrh%%?\t%%0, %%2, #%d", i); >>> + snprintf (templ, sizeof (templ), "tinsrh%%?\t%%0, %%2, #%d", i); >>> break; >>> case V2SImode: >>> - sprintf (templ, "tinsrw%%?\t%%0, %%2, #%d", i); >>> + snprintf (templ, sizeof (templ), "tinsrw%%?\t%%0, %%2, #%d", i); >>> break; >>> default: >>> gcc_unreachable (); >>> diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md >>> index >>> e2fdfbb04621ee6f8603849be089e8bce624214d..54e6edfc4c053f685c8ca0cd3d1227015654aca1 >>> 100644 >>> --- a/gcc/config/arm/neon.md >>> +++ b/gcc/config/arm/neon.md >>> @@ -43,9 +43,10 @@ (define_insn "*neon_mov<mode>" >>> gcc_assert (is_valid != 0); >>> if (width == 0) >>> - return "vmov.f32\t%P0, %1 @ <mode>"; >>> + return "vmov.f32\t%P0, %1 @ <mode>"; >>> else >>> - sprintf (templ, "vmov.i%d\t%%P0, %%x1 @ <mode>", width); >>> + snprintf (templ, sizeof (templ), >>> + "vmov.i%d\t%%P0, %%x1 @ <mode>", width); >>> return templ; >>> } >>> @@ -88,9 +89,10 @@ (define_insn "*neon_mov<mode>" >>> gcc_assert (is_valid != 0); >>> if (width == 0) >>> - return "vmov.f32\t%q0, %1 @ <mode>"; >>> + return "vmov.f32\t%q0, %1 @ <mode>"; >>> else >>> - sprintf (templ, "vmov.i%d\t%%q0, %%1 @ <mode>", width); >>> + snprintf (templ, sizeof (templ), >>> + "vmov.i%d\t%%q0, %%1 @ <mode>", width); >>> return templ; >>> } >>> @@ -2346,12 +2348,13 @@ (define_insn "neon_vc<cmp_op><mode>_insn" >>> && !flag_unsafe_math_optimizations)" >>> { >>> char pattern[100]; >>> - sprintf (pattern, "vc<cmp_op>.%s%%#<V_sz_elem>\t%%<V_reg>0," >>> - " %%<V_reg>1, %s", >>> - GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT >>> - ? "f" : "<cmp_type>", >>> - which_alternative == 0 >>> - ? "%<V_reg>2" : "#0"); >>> + snprintf (pattern, sizeof (pattern), >>> + "vc<cmp_op>.%s%%#<V_sz_elem>\t%%<V_reg>0," >>> + " %%<V_reg>1, %s", >>> + GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT >>> + ? "f" : "<cmp_type>", >>> + which_alternative == 0 >>> + ? "%<V_reg>2" : "#0"); >>> output_asm_insn (pattern, operands); >>> return ""; >>> } >>> @@ -2370,10 +2373,11 @@ (define_insn >>> "neon_vc<cmp_op_unsp><mode>_insn_unspec" >>> "TARGET_NEON" >>> { >>> char pattern[100]; >>> - sprintf (pattern, "vc<cmp_op_unsp>.f%%#<V_sz_elem>\t%%<V_reg>0," >>> - " %%<V_reg>1, %s", >>> - which_alternative == 0 >>> - ? "%<V_reg>2" : "#0"); >>> + snprintf (pattern, sizeof (pattern), >>> + "vc<cmp_op_unsp>.f%%#<V_sz_elem>\t%%<V_reg>0," >>> + " %%<V_reg>1, %s", >>> + which_alternative == 0 >>> + ? "%<V_reg>2" : "#0"); >>> output_asm_insn (pattern, operands); >>> return ""; >>> } >>> >