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

AltStyle によって変換されたページ (->オリジナル) /