Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

-std=gnu99 broke build on CentOS 7 #5611

Closed
solardiz opened this issue Dec 11, 2024 · 6 comments · Fixed by #5619
Closed

-std=gnu99 broke build on CentOS 7 #5611

solardiz opened this issue Dec 11, 2024 · 6 comments · Fixed by #5619
Assignees
Labels
portability regression Bug introduced with certain change(s), causing performance degradation or feature loss

Comments

@solardiz
Copy link
Member

#5600 broke build (or rather the final linking) on our "well" as follows:

dynamic_fmt.o: In function `DynamicFunc__crypt_md5':
/home/solar/j/bleeding-jumbo-20241211/src/dynamic_fmt.c:5274: undefined reference to `MD5_body_for_thread'
dynamic_fmt.o: In function `DynamicFunc__POCrypt':
/home/solar/j/bleeding-jumbo-20241211/src/dynamic_fmt.c:5373: undefined reference to `MD5_body_for_thread'
dynamic_fmt.o: In function `DynamicFunc__crypt2_md5':
/home/solar/j/bleeding-jumbo-20241211/src/dynamic_fmt.c:5416: undefined reference to `MD5_body_for_thread'
dynamic_fmt.o: In function `DynamicFunc__crypt_md5_in1_to_out2':
/home/solar/j/bleeding-jumbo-20241211/src/dynamic_fmt.c:5500: undefined reference to `MD5_body_for_thread'
dynamic_fmt.o: In function `DynamicFunc__crypt_md5_in2_to_out1':
/home/solar/j/bleeding-jumbo-20241211/src/dynamic_fmt.c:5586: undefined reference to `MD5_body_for_thread'
dynamic_fmt.o:/home/solar/j/bleeding-jumbo-20241211/src/dynamic_fmt.c:5674: more undefined references to `MD5_body_for_thread' follow

I've tried adding -std=gnu99 also at link time, but this made no difference.

gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) 
@solardiz solardiz added portability regression Bug introduced with certain change(s), causing performance degradation or feature loss labels Dec 11, 2024
@solardiz solardiz added this to the Definitely 2.0.0 milestone Dec 11, 2024
@solardiz
Copy link
Member Author

solardiz commented Dec 11, 2024

I've confirmed that b1d063a is the exact commit that causes this breakage. Checking out 6433323 (the previous commit) builds fine. Edit: Also, git revert b1d063a3d5da9abb66ed434a34d9e679ccc8fb18 on our latest tree as of today makes it build again.

@magnumripper
Copy link
Member

I was convinced this would make it work (while figuring out why)

diff --git a/src/common.h b/src/common.h
index a0b7535..2a37e13 100644
--- a/src/common.h
+++ b/src/common.h
@@ -60,8 +60,6 @@
 #else
 #define MAYBE_INLINE __inline__
 #endif
-#elif __STDC_VERSION__ >= 199901L
-#define MAYBE_INLINE inline
 #else
 #define MAYBE_INLINE
 #endif

But it doesn't make any difference.

magnumripper added a commit to magnumripper/john that referenced this issue Dec 18, 2024
"dynamic_fmt.c:5274: undefined reference to `MD5_body_for_thread'"

Non-static function using "inline" doesn't get external linkage unless also
declared with "extern" somewhere.

I'm not 100% sure but this one compiler may actually do the right thing while
all the ones not bailing out break the standard for compatibility reasons.

Closes openwall#5611
@magnumripper
Copy link
Member

TIL that the idea of the C99 way of doing this, is you should put the definition of the inline function in the header file:

inline void func(...)
{
    ... actual code ...
}

and only a declaration (adding extern) in the corresponding .c file:

extern inline void func(...);

That last thing triggers external linkage.

It sounds backwards until you think again: Any file sourcing the header can get the full function for inlining, but if they don't inline it, the extern declaration ensured there's linkage. I never understood this until now.

@solardiz
Copy link
Member Author

FWIW, the Linux kernel appears to do this backwards - their only uses of extern inline are in header files, but they redefine inline to mean pre-C99 __gnu_inline:

/*
 * Prefer gnu_inline, so that extern inline functions do not emit an
 * externally visible function. This makes extern inline behave as per gnu89
 * semantics rather than c99. This prevents multiple symbol definition errors
 * of extern inline functions at link time.
 * A lot of inline functions can cause havoc with function tracing.
 */
#define inline inline __gnu_inline __inline_maybe_unused notrace

... and there I was hoping to use Linux as our example of how to do it right. Well, it may be right for what's needed there, but not for a more portable project such as ours.

@solardiz
Copy link
Member Author

Linux kernel appears to do this backwards - their only uses of extern inline are in header files, but they redefine inline

Also, they have extern inline directly followed by the function body. They do not use separate inline for definition + extern inline for declaration as in @magnumripper's comment above. I don't know if that shortcut is portable.

@solardiz
Copy link
Member Author

solardiz commented Dec 23, 2024

@magnumripper I think you may partially misunderstand the extern line in .c file thing. I think it was only needed for MD5_body_for_thread because dynamic_types.h has it as extern without including a header file that would have it. I think this extern inline thing is not strictly required as a defense against the compiler just choosing not to inline despite of the inline keyword - that would work just fine anyhow when the right header file with the function definition is included where the function is needed (edit: but would be wasteful if this happens more than once in different translation units including that header file).

MD5_body_for_thread is neither defined nor declared in a header file other than dynamic_types.h. It is defined solely in a C file, MD5_std.c. So its reuse in dynamic_types.h was a hack and it remains a hack now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
portability regression Bug introduced with certain change(s), causing performance degradation or feature loss
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants