0

My coworker came to me with a problem yesterday.

He has a CL with two variables defined, 10 characters each. He then calls another CL with the first variable as a parameter, and after the CL comes back (which is a long string of programs which will likely have to be manually combed through for the offending code), his first variable is unchanged, but the first 5 characters of his second variable are blanked out.

Because the parameters are passed by reference there is obviously something that is able to affect more than the 10 bytes allotted and it is overflowing to the variable defined immediately after it in memory, but I'm wondering what common examples of this would be (that would not result in some kind of explicit error). Another program that is getting this address passed to it that has its parameters defined with 15 bytes? Using a pointer to the address and then dereferencing and assigning a 15 character string? This is V7R1.

In the meantime he stuck another variable between the two to act as a buffer lol. Interestingly enough, variables that are not assigned a value are never initialized so they are not given any space in memory. Interesting thing to discover when playing around with this.

Ryan
  • 76
  • 7
  • If a 10 character CL field is passed to a 15 character field in another program (am I understanding that correctly?) then can easily see how it would be truncated 5 characters. it would help to know the language of the receiving progra. In RPG and COBOL moving values often occurs right-to-left (i.e. "1234567890" would become "_____1234567890" , then "_____12345". It should be possible to put the the CL in debug, watch/monitor the variable, to isolate where the value is being changed. – Richard Evans Aug 10 '17 at 12:55
  • Could be confusion about how parameters should be used. There is another question https://stackoverflow.com/q/45471550/2296441 that has similar confusion. Maybe a downstream program is simply laying a data structure that "works" over the first parameter and is attempting to maintain both parameters! – jmarkmurphy Aug 10 '17 at 14:39
  • Not that that is a good way to do things. – jmarkmurphy Aug 10 '17 at 14:39
  • Most likely some program changed the variable. That's what programs do. If you want to save on programming insurance.... – danny117 Aug 11 '17 at 14:53

3 Answers3

3

All is takes is for a program further down in the call stack to have a parameter mis-defined

calling program

/*pgm a*/
pgm
  dcl &parm1 char(10) value('Hello')
  dcl &parm2 char(10) value('Charles')

  call pgmb parm(&parm1 &parm2)
endpgm

called program

/*pgm b*/
pgm parm(&parmA &parmB)
  dcl &parmA char(15)
  dcl &parmB char(10)

  chgvar &parmA value('Bye')
endpgm

Note: It's not guaranteed to break, it might work fine, till some PTF is applied that changes the internals of the OS or just the compiler.

I personally saw where an RPG III program had been working "fine" for years, that broke when converted to RPGIV due to differences in how the compiler laid out memory. The RPG III program was corrupting unused memory, but at RPGIV the corrupted memory had been important.

Bottom line, count yourself lucky that an error is being thrown...trace down through the call stack to find the mismatch.

Charles
  • 21,637
  • 1
  • 20
  • 44
  • No error is being thrown, hence the question. I tried this example and the second variable is intact. I was thinking along the same lines, though, and that it is calling a program that was compiled quite a long time ago whose behavior is less secure and more strict (ie if you tell it to update 15 bytes, it updates 15 bytes, whereas now if you tell it to update 15 bytes of a 10 byte field, it updates 10). – Ryan Aug 11 '17 at 20:30
  • @Ryan Compile the two programs as OPM CL, source type CLP, rather than as ILE CL, source type CLLE. Assuming the minor typos are corrected, the expected behavior should show that the 2nd parm value has been corrupted in its initial 5 bytes. It takes a little variation to get similar behavior in ILE CL, but be assured that it can be done. – user2338816 Aug 17 '17 at 12:41
1

Defining another variable between the two variables won't necessarily make a difference. There is no guarantee that variables are laid out in storage in the same order they are defined in the program.

To ensure there is additional storage following a variable, the extra storage must be defined explicitly.

In CL, do it like this. This will add a guaranteed extra 90 bytes following &MYVAR.

dcl &myvar_stg type(*char) len(100)                                 
   dcl &myvar type(*char) stg(*defined) len(10) defvar(&myvar_stg 1)
Barbara Morris
  • 3,195
  • 8
  • 10
0

Assuming all the programs involved are debuggable, you can find out exactly where the storage is getting corrupted by putting a watch on the second variable in debug.

In the debugger, use the "watch" command and then let the program run.

===> watch &myvar2

You'll get a watch breakpoint on the next debuggable statement following the statement that changed the storage. Usually, the next debuggable statement is in the same program that changed the storage.

Barbara Morris
  • 3,195
  • 8
  • 10