On Thu, Oct 7, 2021 at 9:48 PM Denys Vlasenko <[email protected]> wrote:
>
> On Thu, Oct 7, 2021 at 3:25 PM 余生与君 <[email protected]> wrote:
> > > 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.
>
> Aha...
> The problem here is that even though later uses of "p" in this block
> where we use ASSIGN_CONST_PTR() macro will use the local "p" pointer,
> when we exit the block, the following uses will refer to the global one.
> Nothing prevents them to still use incorrect value.
> The fix depends only on the hope that there won't be such uses.
> But they already exist:
>
> inetd.c:
>         INIT_G();
>         real_uid = getuid();
>
> ftpgetput.c:
>         INIT_G();
>         /* Set default values */
>         user = "anonymous";
>         password = "busybox";

Yes, I noticed that, and that's why I removed do-while in the INIT_G
in this patch.

> Can you try something more? E.g. (in current git):
>
> #define ASSIGN_CONST_PTR(p, v) do { \
>         *(void**)not_const_pp(&p) = (void*)(v); \
>         /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
>         barrier(); \
> +       sleep(0); \
> } while (0)

Cool! Sleep(0) does the magic!

ADRP            X21, #ash_ptr_to_globals_misc_ptr@PAGE
LDR             X21, [X21,#ash_ptr_to_globals_misc_ptr@PAGEOFF]
MOV             X8, X21
STR             X0, [X8]
MOV             W0, WZR
BL              sleep
LDR             X21, [X21]


And further investigation shows that a dummy function can also do this trick!

hack.c:
void clang_barrier() {
}

libbb.h:
void clang_barrier(); // invisible in this file
#define ASSIGN_CONST_PTR(p, v) do { \
        *(void**)not_const_pp(&p) = (void*)(v); \
        /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
-        barrier(); \
+       clang_barrier(); \
} while (0)

Result:
ADRP            X21, #ash_ptr_to_globals_misc_ptr@PAGE
LDR             X21, [X21,#ash_ptr_to_globals_misc_ptr@PAGEOFF]
MOV             X8, X21
STR             X0, [X8]
BL              clang_barrier
LDR             X21, [X21]

I will submit a patch about this.

> or even
>
> -       barrier(); \
> +       pselect(0, NULL, NULL, NULL, {0,0}, NULL); \
>
> Basically, we should convince clang to not load "p" too early,
> by starving it of available registers to store the fetched result.
>
> > > 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.
>
> I'm not even sure other compilers would interpret it like that -
> they might think that "p" inside ({}) is the newly defined one.

That's why I only apply it to clang to avoid other compilers having
different behavior.
But in c++14, this is UB. The `p` is the newly defined one. But we can
avoid this to two statements with a tmp variable. But the name can be
conflicted.
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to