HP3000-L Archives

April 2002, Week 1

HP3000-L@RAVEN.UTC.EDU

Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Steve Dirickson <[log in to unmask]>
Reply To:
Steve Dirickson <[log in to unmask]>
Date:
Thu, 4 Apr 2002 15:52:34 -0800
Content-Type:
text/plain
Parts/Attachments:
text/plain (107 lines)
Question:

> >In IMAGE DBGET, what happens if the LIST of ITEMS is longer
> >than the BUFFER being put into.
> >Besides the obvious truncation, is there any impact?

Answers:

> Sorry, there is no truncation, obvious or hidden.  If you ask
> for 100 bytes
> of data via the item list, and your buffer is only 90 bytes,
> expect the
> other 10 bytes to comeback in next 10 bytes of your working
> storage (Cobol)
> or whatever functions as the next 10 byes in the stack in
> other languages,

or

> In FORTRAN/77, the data retrieved will overwrite whatever is
> next in memory if the buffer area is not big enough.

or

> Plenty of people have already indicated that what you get is
extremely
> unpredictable program behavior, due to overwriting of
> whatever data space
> happens to be "to the right" of your buffer area. I've seen
> people get bit
> on this when the dataset record length increases and the
> buffer definition
> does not get changed accordingly. This can 'lurk' for a long
> time as that
> occasional bug that can't be reproduced in captivity, or it could
just
> plain cause something obvious like an abort.

However:

> In Basic/V, IIRC, you get an error telling you insufficient
> buffer, because
> the interface can add up how much space you have given it to
> return the data.

1) At the IMAGE level, the returned data will, if required, overwrite
the buffer area provided. This is due to the defective design of the
DBGET intrinsic, which allows you to provide the address of the buffer
area into which the returned data is to be written, but does not allow
you to specify the maximum amount of data you are willing to receive.
It would have been trivially easy to add a 'buflen' parameter to pass
this information, thus allowing developers in all languages to protect
themselves from (at least some) data item/set changes, but it wasn't
done that way. (Take this as a general indictment of any pointer-only
API: any interface that accepts a pointer to a buffer into which it is
to write data, but doesn't also accept--and respect--a value
specifying the maximum amount of data it is allowed to write into that
buffer, is broken)

2) Depending on the language, this may or may not cause a real
data-overwrite problem. Most languages work at a fairly low level, and
unexpectedly-long data will trash something important. However, some
languages, like BASIC/V and the original Transact/V (don't know about
Transact/iX), appear to "double buffer" the data transfer: they appear
to accept the actual DBGET result into a runtime-owned buffer--which
is presumably as long as the largest possible data transfer--and then
copy the data to your buffer only if it looks kosher. So, if the data
coming from DBGET (as indicated by the 'length' field of the 'status'
parameter) doesn't match the expected length, you get a runtime error
from the language system instead of a stack overwrite and a VSM DMPT
abort.

As also mentioned, you can (usually) code to detect this situation,
even if you can't prevent it: compare the size of the struct, record,
or whatever data construct you use to receive the data with the length
of the data DBGET said it returned. If your structure doesn't match
the data set layout due to item additions, deletions, or size changes,
the two won't match. In C, this looks something like

struct {
   /* whatever */
  } setimage;

DBGET((short*)base, (short*)set, &MODE5, &dbstatus,
          (short*)"@;" /*or (short*)"ITEM1,ITEM3,ITEM7;"*/,
(short*)&setimage, &dummyarg);
if (0 != dbstatus.condition)
        {
        /* appropriate error analysis/handling */
        }
else
        {
        /* attempt to catch data item size changes */
        ASSERT(sizeof(setimage) / 2 == dbstatus.length);
        /* process the data */
        }

However, this won't protect you against a shuffling of the items in
the set, or against multiple, offsetting item changes that cause the
layout of the set to change without modifying the total length of the
set (or the subset of items selected). You can use DBINFO to verify
the exact contents of the set at runtime; few choose this (admittedly
high-overhead) option.

* To join/leave the list, search archives, change list settings, *
* etc., please visit http://raven.utc.edu/archives/hp3000-l.html *

ATOM RSS1 RSS2