> where p is a dummy, unused variable
No. p here shadows the global variable with the same name local
variable so the following context (scope) will use this local variable
instead of the global one.
> Also, why ({...;})
That is to avoid conflict between the global variable and the local
variable. When the ({...}) part is evaluating, it uses the global
variable p and stores it into the local variable, and then returns the
variable to initialize the local variable.
> Can we try something more stable?
`volatile` does not work as I tested. It's because the global variable
is const so the compiler assumes it won't change no matter other
variables are volatile or not. That's why I make a shadow local
variable to make sure the following context uses a new but initialized
const local variable instead of the global and potentially
uninitialized one.
On Thu, Oct 7, 2021 at 9:06 PM Denys Vlasenko <[email protected]> wrote:
>
> On Wed, Sep 29, 2021 at 11:37 AM LoveSy <[email protected]> wrote:
> >
> > From: YU Jincheng <[email protected]>
> >
> > - clang 9+ will load the const pointer first before the const
> > pointer assignment trick and thus cause null pointer defer.
> > - This patch creates a shadow variable to prevent the above from
> > happening for clang 9+.
> > - Also, this patch applies `BB_GLOBAL_CONST` to all variables
> > using the same trick, allowing archs or toolchains having the
> > same issue to bypass this trick correctly.
> >
> > This patch fixes https://bugs.busybox.net/show_bug.cgi?id=14231
> > and https://bugs.busybox.net/show_bug.cgi?id=14236
> >
> > Co-authored-by: canyie <[email protected]>
> > Signed-off-by: YU Jincheng <[email protected]>
> ....
> > +#define ASSIGN_CONST_PTR(p, v) \
> > +_Pragma("clang diagnostic push"); \
> > +_Pragma("clang diagnostic ignored \"-Wshadow\""); \
> > + __typeof__(p) p = ({*(void**)not_const_pp(&p) = (void*)(v);});
> > +_Pragma("clang diagnostic pop")
> > +#endif
>
> So, you observe that
>
> *(void**)not_const_pp(&p) = (void*)(v);
>
> does not work, but
>
> void *p = ({*(void**)not_const_pp(&p) = (void*)(v);});
>
> (where p is a dummy, unused variable) works?
> This is kind of surprising, since dummy variable can be completely
> eliminated by the optimizer, making above statements equivalent.
> (Also, why ({...;})? Does
> void *p = *(void**)not_const_pp(&p) = (void*)(v);
> work too?)
>
> Can we try something more stable?
> For example, try this:
>
> -static ALWAYS_INLINE void* not_const_pp(const void *p)
> +static ALWAYS_INLINE volatile void* not_const_pp(const void *p)
> {
> - void *pp;
> + volatile void *pp;
>
> or this:
>
> *(void *volatile *)not_const_pp(&p) = (void*)(v);
>
> (we say to compiler that this pointer is to volatile
> storage, specifically a volatile pointer,
> "do not optimize the store").
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox