-
Notifications
You must be signed in to change notification settings - Fork 593
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
portability: locale_t need not be a pointer type #3427
Comments
You are correct in your analysis. We just had a lazy-loader implementation that we could readily use. We have to duplicate and modify that otherwise to work with portable |
All of this to say, there's no easy way to atomically assign a |
You don't even need to ever define such struct... So, I don't see the downside of that, over |
The downside of declaring "struct _locale" without actually using it is that it makes the code harder to understand. We like to keep our code simple, and to avoid needless abstractions. Should application software constrain C libraries to particular implementation choices? I'm not really convinced just yet.
True, i don't think you can atomically assign a locale_t at all.
According to POSIX, sizeof(locale_t) might even be 42 or any other positive integer number. Unless other operating systems contact you where locale_t is actually a struct or an array rather than a pointer, and if you hesitate to do a full cleanup right now, a compromise would be to just make your code work with "void *" and postpone dealing with non-pointer implementations until they are reported to you, hoping that day might never come. Unless i'm missing something, the "operator *" method in the parent class is the only problem that prevents "void *" from working. Do you really need that method, or was it defined just for interface completeness, "just in case"? It clearly isn't used for hb_C_locale_lazy_loader_t. Even if somethings wants to have it, could it be moved to just those child classes of hb_lazy_loader_t that really need it? |
Okay. Let me try to make that conditional. |
@ischwarze see if #3428 helps. Thanks. |
I am happy to confirm that with your patch to src/hb-machinery.hh, harfbuzz-3.3.1 compiles on OpenBSD-amd64-current with clang 13. Antoine is planning to do more extensive testing later. We will let you know of any further issues, but right now, i see no particular reason to expect any. Your friendly and efficient handling of this issue is highly appreciated. Thank you very much! (edit: only a typo fix, no content change) |
Thank you @ischwarze. We'll get this into a release soon. cc @khaledhosny |
|
I think src/hb-common.cc and src/hb-machinery.hh make non-portable assumptions about the properties of the type locale_t. All that POSIX requires is that something of type locale_t is an "object", and i think the word "object" is to be understood in the sense of the C standard. In particular, POSIX does not require locale_t to be a pointer type, and even less so that it points to anything. If i read POSIX correctly, having "typedef int locale_t" in <locale.h> would be perfectly valid.
However, src/hb-common.cc invokes "hb_remove_pointer<locale_t>" which can only work if locale_t is a pointer type. Even worse, the parent class of hb_C_locale_lazy_loader_t, that is, the class hb_lazy_loader_t declared in src/hb-machinery.hh, assumes that locale_t is a pointer to a non-void type: in the declaration of the "operator *" method of hb_lazy_loader_t, it takes a reference to the type pointed to by locale_t:
In case of "typedef void *locale_t", the "void &" contained in this line is a syntax error:
My impression is that all these assumptions are completely gratuitious. I inspected the files src/hb-common.cc, src/hb-machinery.hh, and src/hb-meta.hh and failed to find any code that might actually dereference a locale_t pointer. Also, application code cannot do that because the type hb_C_locale_lazy_loader_t is local to the file src/hb-common.cc rather than contained in any public header, so applications cannot instantiate such an object, and the only object instantiated internally, static_C_locale, is static in the same file, so application code cannot access that object either. As far as i can see, using the excessively generic parent class is not required for any practical purpose, and the only effect is to kill the build. Besides, actually dereferencing locale_t would also be useless because the size and layout of locale_t is system-dependent, and even within any given operating system, the ABI may change from one OS version to the next, so harfbuzz could not usefully peek into the object even if it wanted to.
I think it would be best to clean up your code and let it respect POSIX such that it works with "typedef int locale_t" - or at least with "typedef void *locale_t".
The issue was found by Antoine Jacoutot while trying to port harfbuzz-3.3.1 to the upcoming OpenBSD 7.1 release (OpenBSD is an example of a real-world system using "typedef void *locale_t"). Part of the analysis was done by Marc Espie, part by me.
I'm also considering to change the OpenBSD libc implementation to "typedef struct _locale *locale_t" with a dummy struct, but i'd hate having to do that because we don't really need it and POSIX does not require it. Apart from harfbuzz, i'm not aware of any other software that makes such assumptions, so changing the C library just for harfbuzz feels like an extreme measure to me, in particular given that even harfbuzz doesn't seem to do anything useful with it either.
The text was updated successfully, but these errors were encountered: