|
wrote:
My apologises to all who replied, both on and off the list, for the lack
of response to suggestions as it took me some time to create a set of
tests and checks of various ideas.
On Mon, 2015-08-17 at 17:47 -0400, Barbara Morris wrote:
On 8/12/2015 8:42 AM, Wilson, Jonathan wrote:were
...
But, the caller is the one setting up the "Data" to be returned and as
such I have no control over if this field is long enough, even if I
theto have extra parameters with say the length of the "Data" there is
nothing stopping the caller lying and, as far as I know, there is no
programmable way of finding out the definition (or at least its length)
of the field in the caller that was actually passed.
...
Now to prevent the called service program from corrupting memory, I was
wondering if the use of the %realloc would be sensible way of guarding
against overwriting memory, in the called procedure I always perform a
realloc to set up the data to the desired length prior to setting up
data. Something along the lines of...
I guess I'm a bit late to this thread...
There are (at least) two problems with using %realloc for this.
- If the caller did not use %ALLOC for the parameter, this will not work
at all.
- If the caller used %ALLOC, then they have a pointer to the storage,
and when you use %REALLOC, the caller's pointer will become invalid. If
they try to use the allocated storage they will either get incorrect
results or, much worse, they will cause storage corruption.
CEE0810... so much for that initial idea I had, lol.
A huge misunderstanding on my part as to how pointers and memory worked.
You can't even change the address of the original (although that would
cause a memory leak in the original if it worked) as its the hidden
_PNTR_TO_PARM (not quite the right name but close enough) that is used
to pass parameters... when passing a pointer it turns out that a pointer
to the pointer is passed; which sucks! I'm sure with the right language
and/or knowledge it might be possible to get hold of that "hidden"
pointer, but I'm still working my way with re-learning RPG as it is.
I would use different procedures as others have suggested, and avoid
using pointers at all.
In the end I went with something similar to this, a standard procedure
with the data structure as a parameter definition and no const (so no
possibility of wrong data, assuming prototypes used correctly) and
another parm to limit the amount of data filled into the returned DS -
*KEYSONLY, *FULLRECORD, other. (so the caller has to be careful not to
use KEYSONLY and then try to use the extended data, won't cause
corruption but will not contain valid data... a bug not a crash, and I
may review this idea as I try out DS file I/O)
If it's necessary to do storage allocations for some reason, the safest
thing is to control them all yourself, and not let your callers access
the allocated storage. Instead, just pass back the data they need.
I agree with others that callers should call your procedures correctly,
but I think you're right to worry about the possibility of being called
incorrectly. Programmers do make mistakes, and the penalty (storage
corruption) for passing the wrong parameters may be too harsh for the
crime (say copying one call to your procedure and not fixing up all the
parameters).
You mention corruption... I'm curious as to just how bad that corruption
might be, so I have a few follow on questions.
Lets forget pointers for a min, and assume normal parameter passing
(which uses pointers under the hood).
JOB1 does a procedure call, passing as parm1 a 3 char field.
The called procedure wants a 20KiB string but somehow the programs
compiled (const?) and are fully executable.
The called procedure does a eval parm1 = verylongstring.
Now assuming it doesn't some how get a run time error, what is the worst
that could happen?
I know it could overwrite other passed parms, as I'm sure I've seen that
happen (at least as far as pgm plist parms, but its some time ago now).
Also during my testing I've seen in debug long procedure input parms
passed short fields by the caller contain what looks suspiciously like
code and/or buffer data (not sure if it was caller or called code/data).
So I know, assuming no runtime error that I can corrupt data, but what
about the suspicious looking data, what if its program code that gets
stomped on or the debug included code? (It looked similar to that?)
What if the data is data, not code, is it possible for one job to stomp
over another jobs data?
If I use pointers, is it possible to pass pointers between jobs to see
another jobs data? Can you even do BasedPointerField = AValue? or does
it require AValue to be another basedpointer field? (What about other
languages?)
If job1/pgm1 stores its data at address0101 and job2/pgm5 stores its
data at address0102 and job1/pgm1 somehow manages to clear
address0101-address0107 does it wipe out the data from job2/pgm5 or is
there some magic that protects job memory from other jobs, even though
its all "one huge single level storage". (note in this case its memory
(heap?) storage, as opposed to somehow getting a pointer to a pgm object
and treating it as memory which as far as I can tell is not possible)
Now I know IBM must have thought about all of this, and I know some
things are protected by hardware (non-executable bits. Were?) and some
is protected by not allowing user programs to gain access to things they
shouldn't (getting a memory pointer to point to a pgm object or getting
a pointer to point at an address that is in the middle of a programs exe
code?)
I also know, or at least seem to recall, that the "i" doesn't do bare
metal but uses MI to do most of this protection so a programs exe
doesn't actaully get real hardware addresses, but what about if the box
also runs different environments, is it even possible to write a bit of
code in power8 instructions and some how load that and run it inside or
outside of the "i" environment or boot the hardware to a user supplied
OS/program at the bare metal level?
The last paragraph is purely "I wonder" so any link to articles I can
peruse later would be much appreciated.
Thanks in advance.
--
Barbara
--
This is the RPG programming on the IBM i (AS/400 and iSeries) (RPG400-L)
mailing list
To post a message email: RPG400-L@xxxxxxxxxxxx
To subscribe, unsubscribe, or change list options,
visit: http://lists.midrange.com/mailman/listinfo/rpg400-l
or email: RPG400-L-request@xxxxxxxxxxxx
Before posting, please take a moment to review the archives
at http://archive.midrange.com/rpg400-l.
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.