tech-pkg archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: odd fonts/t1lib compile mystery on osx
On Fri, Jan 04, 2019 at 05:05:34PM -0500, Chuck Cranor wrote:
> I'm on a quest to get math/grace working on osx. Thomas solved a
> x11/motif problem blocking me by updating the package from 2.3.4
> to 2.3.8 (thanks wiz!). So motif programs now work on osx, but grace
> is still crashing...
clearly I'm on the slow boat, but I finally got there. turns out
there are two bugs in fonts/t1lib that cause grace to crash on OSX:
[1] compiler bug in some versions of clang when compiling with "-O2" ...
this appears to have been fixed somewhere between clang-11 and clang-12.
it works ok with "-O1" and it doesn't impact my NetBSD system (which
has gcc instead of clang).
[2] one case of t1lib trying to be clever and instead writing past end of
malloc'd buffer (which the OSX malloc did not like at all; the netbsd
malloc did not get messed up by this). the address sanitizer helped
pinpoint this.
For [1], the t1lib is trying to roll its own optmized memcpy() using
this macro in lib/type1/objects.h:
#define LONGCOPY(dest,source,bytes) { \
register LONG *p1 = (LONG *)dest; register LONG *p2 = (LONG *)source; \
register int count = (bytes) / sizeof(LONG); \
while (--count >= 0) *p1++ = *p2++; }
they explain (in lib/type1/objects.c) they are doing this because
there is no standarized portable memory copy routine (e.g. memcpy()
vs bcopy()). maybe that was true in 1991 when this code was written,
but i think pretty much everyone has memcpy() now?
At any rate, some versions of "clang -O2" choke on LONGCOPY() and
produce incorrect code. I've got a 49 line test C program that
reproduces the issue (see attached xalloc-test.c):
% clang-11 -O1 -o alloc-test xalloc-test.c
% ./alloc-test
Result CORRECT!
% clang-11 -O2 -o alloc-test xalloc-test.c
% ./alloc-test
Result FAILED! (0 != 0x80)
% clang-12 -O2 -o alloc-test xalloc-test.c
% ./alloc-test
Result CORRECT!
%
I think the solution is to assume that memcpy() is going to be
available and have LONGCOPY() use memcpy() rather than its custom
copy.
For [2], the issue is in lib/type1/regions.c where it allocates
"(ymax - iy) * sizeof(pel)" bytes of extra data using malloc and
then uses LONGCOPY() like this:
---------------------------------------------------------------------------
/*
We must round up (ymax - iy) so we get the ceiling of the number of
longs. The destination must be able to hold these extra bytes because
Allocate() makes everything it allocates be in multiples of longs.
*/
LONGCOPY(&r[1], xvalues, (ymax - iy) * sizeof(pel) + sizeof(LONG) - 1);
---------------------------------------------------------------------------
they've incorrectly computed the ceiling by just adding "sizeof(LONG) - 1"
(need to mask off the low bits by "~(sizeof(LONG) - 1)").
with those fixes in, I can run grace on all the examples in
/usr/pkg/grace/examples (using the "dotest" script there) on OSX
without grace crashing.
I will attempt to fix this in pkgsrc.
chuck
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct xobject {
int flag;
};
#define LONGCOPY(dest,source,bytes) do { \
long *p1 = (long *)dest; \
long *p2 = (long *)source; \
int count = (bytes) / sizeof(long); \
while (--count >= 0) \
*p1++ = *p2++; \
} while(0)
struct xobject *t1_Allocate(int size, struct xobject *xtemplate) {
struct xobject *r;
r = (struct xobject *) malloc(size);
if (r == NULL) errx(1, "malloc abort");
#if 1
LONGCOPY(r, xtemplate, size);
#else
memcpy(r, xtemplate, size);
#endif
r->flag &= ~(0x01);
return(r);
}
int main(int argc, char **argv) {
struct xobject *xo, *xo2;
xo = malloc(56);
memset(xo, 0, 56);
xo->flag = 0x80;
xo2 = t1_Allocate(56, xo);
if (xo2->flag == 0x80) {
fprintf(stderr, "Result CORRECT!\n");
} else {
fprintf(stderr, "Result FAILED! (%#x != 0x80)\n", xo2->flag);
}
exit(0);
}
Home |
Main Index |
Thread Index |
Old Index