[cfe-dev] Relaxing format specifier checks

James Y Knight via cfe-dev cfe-dev at lists.llvm.org
Thu May 17 07:52:09 PDT 2018


This is a convincing point, but the reasoning here is somewhat different,
since it's dealing with pointer-types, and then an actual
pointer-dereference of the incorrect type. That's certainly a bad idea -- I
agree it'd be quite unwise to change the behavior when dealing with
pointers, either in the scanf specifiers or for the expected pointee-type
of %n in printf.

I think the question at hand is whether a type-mismatch of the value itself
is a problem you should be worried about. E.g., calling "va_arg(long)" when
passing a value of type int to the call, where int and long are "the same".



On Thu, May 17, 2018 at 1:16 AM Hubert Tong via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> On Fri, May 11, 2018 at 7:26 PM, Shoaib Meenai via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
>> Of course, we should also ensure that the optimizer doesn't do anything
>> surprising when there's a type mismatch between the specifier and the
>> argument but both types have the same size and alignment (i.e., the case
>> where the relaxed format warning won't fire), both now and in the future.
>>
> The "contract" for the format string and the corresponding argument is as
> described elsewhere in the thread, and it is rather more interesting for
> scanf than not. GCC's implementation technology is apparently able to
> optimize (at -O2 and up, at least when targeting powerpc64le-linux-gnu) the
> check feeding the abort() in the following to not observe the write
> performed in the ersatz scanf():
> #include <stdarg.h>
> void abort(void);
> int strcmp(const char *, const char *);
>
> typedef int Type;
> typedef long NType;
>
> int myvscanf(const char *const fmt, va_list ap) {
>   if (strcmp(fmt, "%ld") != 0) { return 0; }
>
>   NType *const p = va_arg(ap, NType *);
>   *p = 42;
>   return 1;
> }
>
> __attribute__((__format__(__scanf__, 2, 3)))
> __attribute__((__noinline__, __noclone__))
> void updateStatusFromPipe(Type *statusp, const char *const fmt, ...) {
>   va_list ap;
>   va_start(ap, fmt);
>   int ret = 0;
>   if (*statusp == 0) {
>     ret = myvscanf(fmt, ap);
>   }
>   va_end(ap);
>   if (ret >= 1 && *statusp != 0) abort();
> }
>
> int main(void) {
>   Type status = 0;
>   updateStatusFromPipe(&status, "%ld", &status);
> }
>
> The "now or in the future" sounds like needing to do "worse" or "better"
> than what GCC is doing to avoid "anything surprising", because "on par"
> with GCC fits the bill for something "surprising". Which is to say that, in
> my opinion, there is no avoiding "something surprising" "in the future" on
> code that the proposed relaxation is letting slip through.
>
> TL;DR: Please don't change the default.
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180517/a0b9c0a1/attachment.html>


More information about the cfe-dev mailing list