[comp.sources.d] tgetent core dump on sco xenix

root@libove.UUCP (The Super User) (06/29/88)

A game was posted some time back called "puzzle". It doesn't work
under SCO Xenix development system 2.1.4g because if compiled with
small model, the single 64K segment isn't sufficient for all its
data, and if compiled under large model it core dumps along the lines
of the much simplified example that follows.

Can anyone explain this?

[root]/tmp:(1 ) % cat argle.c
#include <stdio.h>
#include <sgtty.h>

main()
	{
	char	buffer[1024];

	printf("%d\n",tgetent(buffer,getenv("TERM")));
	};
[root]/tmp:(2 ) % cc -Ml2e -o argle argle.c -ltermcap
argle.c
[root]/tmp:(3 ) % ./argle
./argle: Segmentation violation -- Core dumped
[root]/tmp:(4 ) % adb argle core
* $c
  tnamatch1d82efe8(5436., 0.)	from   tget1ent1d82efe8+320.
  tget1ent1d82efe8(4280., 71., 5436., 0.)	from _tgetent+29.
_tgetent(4280.,	71., 5436.)	from _main+38.
_main(1., 5338., 71., 5346., 71.)	from __start+94.
__start()	from start0+7.
* 
[root]/tmp:(5 ) % cc -o argle argle.c -ltermcap
argle.c
[root]/tmp:(6 ) % ./argle
1
[root]/tmp:(7 ) % 

This is an a PCs Limited AT (IBM PC/AT clone, 8 Mhz) with SCO Xenix 2.2.1
(modified with Ptydriver) and 2.1.4g development system.

Jay Libove               Internet: libove@cs.cmu.edu libove@andrew.cmu.edu
5313 Ellsworth Avenue              formtek!ditka!libove!libove@pt.cs.cmu.edu
Pittsburgh, PA 15232         UUCP: cmucspt!formtek!ditka!libove!libove
(412) 621-9649                     cadre!pitt!darth!libove!libove

rosso@sco.COM (Ross Oliver) (07/02/88)

In article <54@libove.UUCP> Jay Libove illistrates the single most
common mistake in large-model 286 programs.  The example he gives,
when compiled using "cc -M2l..." will dump core on execution:

>#include <stdio.h>
>#include <sgtty.h>
>
>main()
>	{
>	char	buffer[1024];
>
>	printf("%d\n",tgetent(buffer,getenv("TERM")));
>	};

Note that the return value of getenv() is not declared, therefore,
the compiler assumes int.  However, tgetent is expecting a char *,
and in large-model 286 programs, int != char *.  So, when main()
calls tgetent, it passes only two of the four bytes returned by
getenv().  tgetent picks up garbage data as the other two bytes,
and (suprise!) a segmentation violation results.  How can this be
fixed?  With the following declaration:

	char *getenv();

Here are a few tips to avoid problems like this in large-model
286 programs:

    - Declare your functions' return values.
    - Don't use "0" to mean NULL ( i.e. (char *)0 ).
    - Don't interchange ints and pointers, or longs and pointers.


Ross Oliver
SCO Technical Support

james@bigtex.uucp (James Van Artsdalen) (07/04/88)

IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
> Here are a few tips to avoid problems like this in large-model
> 286 programs:

>     - Declare your functions' return values.
>     - Don't use "0" to mean NULL ( i.e. (char *)0 ).

This last statement is incorrect, or rather, evidence of a broken
compiler.

C requires that the integer constant 0 be assignable to *any* pointer
type.  C also requires that any pointer type may be compared with the
integer constant 0.  If the Xenix compiler requires that the integer
constant 0 be cast to a pointer type first, it is broken.
-- 
James R. Van Artsdalen   ...!ut-sally!utastro!bigtex!james   "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746

markz@ssc.UUCP (Mark Zenier) (07/05/88)

In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes:
: IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
: > Here are a few tips to avoid problems like this in large-model
: > 286 programs:
: 
: >     - Declare your functions' return values.
: >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).
: 
: This last statement is incorrect, or rather, evidence of a broken
: compiler.
> 
: C requires that the integer constant 0 be assignable to *any* pointer
: type.  C also requires that any pointer type may be compared with the
: integer constant 0.  If the Xenix compiler requires that the integer
: constant 0 be cast to a pointer type first, it is broken.

Until  ANSI C exists, there is no way the compiler can tell type of the 
expression for a function arguement that is pushed on the stack.
It would have been safer but much slower if Microsoft has chosen the
default integer size at 32 bits for large model compiles.

Mark Zenier	uunet!pilchuck!ssc!markz		
"Kinda scary. One guy said he had heard they were a bunch of wierdo gourmets
from somewhere in Orange County, looking for new taste thrills." 

john@jetson.UUCP (John Owens) (07/05/88)

In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes:
> >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).

> C requires that the integer constant 0 be assignable to *any* pointer
> type.  C also requires that any pointer type may be compared with the
> integer constant 0.  If the Xenix compiler requires that the integer
> constant 0 be cast to a pointer type first, it is broken.

Correct, as far as it goes.  0 must be *assignable* to any pointer
type, and the Xenix C compiler should extend it appropriately.  Also,
when using ANSI C function prototypes, 0 in an argument should be
extented to the size of a pointer.

But in non-ANSI C, in a large-data model, when passing a null pointer
as an argument to a function expecting a pointer argument, "0" will
not do, but "(pointer-type *)0" will.  This indicates nothing wrong
with the Xenix C compiler.]

[For anyone who's still not convinced, make the analogy to floats
(doubles, actually).  While
	double f;
	f = 0;
works, and
	double f;
	extern double fabs();
	f = fabs((double)0);
works,
	double f;
	extern double fabs();
	f = fabs(0);	/* expects a double */
will not.]

-- 
John Owens		SMART HOUSE Limited Partnership
john@jetson.UUCP	(old uucp) uunet!jetson!john
+1 301 249 6000		(internet) john%jetson.uucp@uunet.uu.net

peter@ficc.UUCP (Peter da Silva) (07/07/88)

In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes:
> IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
> > Here are a few tips to avoid problems like this in large-model
> > 286 programs:

> >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).

> This last statement is incorrect, or rather, evidence of a broken
> compiler.

He's speaking in the context of a function call. Large model 286
programs have 32 bit pointers but 16 bit integers, so if you pass
0 to a function expecting a pointer the stack will be off by two
bytes.

So, the problem isn't a broken compiler, it's a broken CPU architecture.
-- 
-- `-_-' Peter (have you hugged your wolf today) da Silva.
--   U   Ferranti International Controls Corporation.
-- Phone: 713-274-5180. CI$: 70216,1076. ICBM: 29 37 N / 95 36 W.
-- UUCP: {uunet,academ!uhnix1,bellcore!tness1}!sugar!ficc!peter.

tif@cpe.UUCP (07/08/88)

Written  1:42 pm  Jul  6, 1988 by ficc.UUCP!peter in cpe:comp.sources.d
>So, the problem isn't a broken compiler, it's a broken CPU architecture.

The problem is broken programming practices.   1/2 :-)

			Paul Chamberlain
			Computer Product Engineering, Tandy Corp.
			ihnp4!sys1!cpe!tif

allbery@ncoast.UUCP (Brandon S. Allbery) (07/09/88)

As quoted from <54@libove.UUCP> by root@libove.UUCP (The Super User):
+---------------
| [root]/tmp:(1 ) % cat argle.c
| #include <stdio.h>
| #include <sgtty.h>
| 
| main()
| 	{
| 	char	buffer[1024];
| 
| 	printf("%d\n",tgetent(buffer,getenv("TERM")));
| 	};
| [root]/tmp:(2 ) % cc -Ml2e -o argle argle.c -ltermcap
| argle.c
| [root]/tmp:(3 ) % ./argle
| ./argle: Segmentation violation -- Core dumped
+---------------

If you use large model you have to include an "extern char *getenv();", or
tgetent() will get a truncated pointer:  C passes an undeclared function
argument as an (int), which is 2 bytes, but a large-model (char *) is 4
bytes.  This is an example of a gratuitous 680x0/Vax-ism, nonportable to
systems where sizeof (int) != sizeof (char *).

The core dump occurs when tnamatch() tries to access the string passed to
it, and gets a pointer with a random value.
-- 
Brandon S. Allbery, uunet!marque!ncoast!allbery			DELPHI: ALLBERY
	    For comp.sources.misc send mail to ncoast!sources-misc

allbery@ncoast.UUCP (Brandon S. Allbery) (07/12/88)

As quoted from <3222@bigtex.uucp> by james@bigtex.uucp (James Van Artsdalen):
+---------------
| IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
| > Here are a few tips to avoid problems like this in large-model
| > 286 programs:
| 
| >     - Declare your functions' return values.
| >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).
| 
| C requires that the integer constant 0 be assignable to *any* pointer
| type.  C also requires that any pointer type may be compared with the
| integer constant 0.  If the Xenix compiler requires that the integer
| constant 0 be cast to a pointer type first, it is broken.
+---------------

Only true in all cases IF (1) your compiler supports ANSI prototypes and (2)
you use them.  Otherwise, passing untyped 0 to a function expecting a pointer
fails for the same reason that the getenv() in the original code did:  the
compiler can't figure out what type is needed there, so it uses (int).
-- 
Brandon S. Allbery, uunet!marque!ncoast!allbery			DELPHI: ALLBERY
	    For comp.sources.misc send mail to ncoast!sources-misc