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 Sat, Jan 05, 2019 at 02:01:20PM +0100, Rhialto wrote:
> Could it be that this #define isn't included for all cases where it is
> needed? It would have been better if the author had not relied on this
> #define, but actually have replaced all cases of abort with t1_abort.

i just tried this but it didn't help.   i removed the #define 
for abort(line,no) and replaced all calls to abort(line,no) to
calls to t1_abort(line,no).  test program still crashes...



> Having even the definition of t1_abort depend on the renaming is really
> too lazy.

My guess as to what is going on here is that the author of t1lib 
(Rainer Menzner) imported the code in lib/type1 from some
upstream IBM distribution and didn't want change the upstream code 
too much.  So he used pre-processor #defines to do renaming instead.   
e.g. if you look at lib/type1/objects.h it's got a bunch of these renames:

#define   abort(line,no)       t1_abort(line,no)
#define   Allocate(n,t,s)   t1_Allocate(n,t,s)
#define   Free(obj)         t1_Free(obj)
#define   NonObjectFree(a)  free(a)
#define   Consume           t1_Consume
#define   ArgErr(s,o,r)     t1_ArgErr(s,o,r)
#define   TypeErr(n,o,e,r)  t1_TypeErr(n,o,e,r)
#define   Copy(obj)         t1_Copy(obj)
#define   Unique(obj)       t1_Unique(obj)



> >      #define xabort(A,B) do { fprintf(stderr, "ABORT!\n"); exit(1); } while (0)
> 
> I would have expected it to work at this point, since (if I followed
> this correctly) there are no cases of abort() any more that are not the
> standard abort().
> 
> Maybe t1lib is doing equally silly things with exit()??? Did it print
> ABORT!?

It never prints "ABORT" ... I don't think abort() [i.e. t1_abort()]
is ever called because there is no error in the test program.  it 
should just work, no aborts.   But it seems like changing the abort
code (even though it is never actually called) makes the difference.

in the xabort() macro, if the last statement is a function annotated
with __dead2, then the test program crashes.   if it ends with a normal
function, then the test program works.   in either case, I don't think
abort is actually called.

oh, and all this works fine on my NetBSD/i386 box.  i'm only seeing
the crash on my osx systems.


I did some more debugging and narrowed down the problem to one single
call to abort() within lib/type1/objects.c ... if I replace that one
abort called with a fprintf(stderr, ...)  [note: fprintf is not a __dead2 
function], then everything runs fine.   The diff is simply:


--- orig_src/t1lib-5.1.2/lib/type1/objects.c	2007-12-23 10:49:42.000000000 -0500
+++ fix_src/t1lib-5.1.2/lib/type1/objects.c	2019-01-05 13:37:33.000000000 -0500
@@ -314,7 +314,9 @@
                if (!GimeSpace()) {
                        IfTrace1(TRUE, "malloc attempted %d bytes.\n",
                                            size + extra);
-                       abort("We have REALLY run out of memory", 16);
+                       //abort("We have REALLY run out of memory", 16);
+                       // XXXCDC: this makes it work?
+                       fprintf(stderr, "We have REALLY run out of memory");
                }
                r = (struct xobject *) malloc(size + extra);
        }


the above is part of some sort of malloc wrapper function.... [I'll
copy the full function below]



I also made a standalone downloadable test in case anyone else
can help look at it.  To run it, download and run the "==README" script:

	wget http://yogi.pdl.cmu.edu/~chuck/tmp/osx-t1lib-test.tgz
	tar xzf osx-t1lib-test.tgz
	cd osx-t1lib-test
	./==README

It includes the t1lib-5.1.2.tar.gz from pkgsrc distfiles and my
test program ("testin.c").  It compiles 2 versions of t1lib:
orig_src is the unmodified version that crashes, fix_src is a 
version with the above patch applied.


This is what I get:

> ./==README 
+ ./RESET
base directory is /tmp/bb/osx-t1lib-test
unpacking t1lib-5.1.2.tar.gz in orig_src fix_src
running orig_src configure - save output to orig_src/cfg.log
running fix_src configure - save output to fix_src/cfg.log
overwrite 'fix_src/t1lib-5.1.2/lib/type1/objects.c' w/fixed version
+ ./REBUILD
base directory is /tmp/bb/osx-t1lib-test
building and installing orig_src in prefix /tmp/bb/osx-t1lib-test/o
log in orig_src/make.log
building and installing fix_src in prefix /tmp/bb/osx-t1lib-test/f
log in fix_src/make.log
done
+ ./RUN-TEST
base directory is /tmp/bb/osx-t1lib-test
building test prog with orig_src - output o-testin
building test prog with fix_src - output f-testin

running o-testin, expect segfault
pre-try_crash
./RUN-TEST: line 19: 78009 Segmentation fault: 11  ./o-testin

running f-testin, expect it to run without error
pre-try_crash
post-try_crash
+ exit 0
> 

takes about 1 minute to try on my osx laptop.   "o-testin"
(crashes with segv) is testin.c linked with "orig_src" ...
"f-testin" is the same program linked with "fix_src" instead.


chuck

here is the orig malloc wrapper function... the issue seems
to be the second call to abort()  ("We have REALLY run out of memory").


struct xobject *t1_Allocate(size, template, extra)  /* non-ANSI; type checking was too strict */
       register int size;    /* number of bytes to allocate & initialize     */
       register struct xobject *template;  /* example structure to allocate  */
       register int extra;   /* any extra uninitialized bytes needed contiguously */
{
 
       register struct xobject *r;
 
       /*
       * round up 'size' and 'extra' to be an integer number of 'long's:
       */
       size = (size + sizeof(LONG) - 1) & -sizeof(LONG);
       extra = (extra + sizeof(LONG) - 1) & -sizeof(LONG);
       if (size + extra <= 0)
               abort("Non-positive allocate?", 15);
       r = (struct xobject *) malloc(size + extra);
 
       while (r == NULL) {
               if (!GimeSpace()) {
                       IfTrace1(TRUE, "malloc attempted %d bytes.\n",
                                           size + extra);
                       abort("We have REALLY run out of memory", 16);
               }
               r = (struct xobject *) malloc(size + extra);
       }
 
       /*
       * copy the template into the new memory:
       */
       if (template != NULL) {
       /* Added references count decrement if template is not permanent.
          This is for the case where Allocate is called by a Dupxxxx
          function, which was in turn called by Unique(). (PNM)        */
               if (!ISPERMANENT(template->flag))
                   --template->references;
               LONGCOPY(r, template, size);
               r->flag &= ~(ISPERMANENT(ON) | ISIMMORTAL(ON));
       /* added reference field 3-2-6-91 PNM */
               r->references = 1;
       }
       else {
               register char **p1;
 
               for (p1=(char **)r; size > 0; size -= sizeof(char *))
                       *p1++ = NULL;
       }
 
       if (MemoryDebug > 1) {
               register int *L;
               L = (int *) r;
               IfTrace4(TRUE, "Allocating at %p: %x %x %x\n",
                                           L, L[-1], L[0], L[1]);
       }
       return(r);
}


Home | Main Index | Thread Index | Old Index