Hey SAS communities,
I'm sharing for your awareness before you decide to migrate to SAS 9.4 M9!
My SAS kicked me in the face today:
1 data _null_;
2 x=42;
3 a = ADDRLONG(x);
4 z = PEEKLONG(a, 8);
5 put x= a= z=;
6 run;
ERROR: The ADDRLONG function is not available beginning with SAS 9.4M9.
ERROR: The PEEKLONG function is not available beginning with SAS 9.4M9.
x=42 a= z=.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
The documentation says:
"Starting in 9.4M9, the ADDRLONG/PEEKLONG function is removed from SAS as a security precaution. The function is no longer supported and should not be used. This function should be removed from DATA step programs to prevent an error."
Bart
One more snippet and its results in M8 and M9:
Code:
data _null_;
x="42";
a = ADDRLONG(x);
length z $2;
z = PEEKcLONG(a,2);
put a=hex16. / (x z) (/=binary64.)
(x z) (/=);
run;
M8 log:
1 %put &sysvlong4.;
9.04.01M8P02222023
2 data _null_;
3 x="42";
4 a = ADDRLONG(x);
5 length z $2;
6 z = PEEKcLONG(a,2);
7 put a=hex16. / (x z) (/=binary64.)
8 (x z) (/=);
9 run;
a=080182541B7F0000
x=0011010000110010
z=0011010000110010
x=42
z=42
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
M9 log:
1 %put &sysvlong4.;
9.04.01M9P06042025
2 data _null_;
3 x="42";
4 a = ADDRLONG(x);
5 length z $2;
6 z = PEEKcLONG(a,2);
7 put a=hex16. / (x z) (/=binary64.)
8 (x z) (/=);
9 run;
ERROR: The ADDRLONG function is not available beginning with SAS 9.4M9.
ERROR: The PEEKCLONG function is not available beginning with SAS 9.4M9.
a=2020202020202020
x=0011010000110010
z=0010000000100000
x=42
z=
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
Bart
This is very surprising, and disappointing. Since an admin could already make these functions unavailable by configuring SAS sessions to run in "lockdown mode," I'm surprised SAS would completely remove the functions.
The What's New has a list of the functions removed in M9. In addition to the variations of ADDR, PEEK, and POKE, we also lost the MODULE functions.
Thanks for the link Quentin!
It says: "These functions were removed from SAS software for security reasons", but I don't understand those decisions... I see no justification...
Bart
@yabwon wrote:
Thanks for the link Quentin!
It says: "These functions were removed from SAS software for security reasons", but I don't understand those decisions... I see no justification...
Bart
In 1979 I watched a fellow computer programming student use similar functions on an HP3000 from a student account give his account system admin abilities. Took him about 5 minutes.
He did really understand the system very well and ended up working at Hewlett Packard before graduating as a software engineer.
As phrase attributed to Linus Torvalds says: "If you know the system well enough, you can do things that aren't supposed to be possible."
The justification used in the documentation, saying: "These functions were removed from SAS software for security reasons" follows the same logic as: "Hammers should be restricted, because they can smash user's finger or other person knee..." 😄
All the best
Bart
Quentin:
Yes, it is, particularly for yours truly. And for quite a few folks who will find out that their production programs no longer work, especially my clients, both former and current.
So, now the once famous SAS backward compatibility is out the window - following the cadre who had made SAS what it was. I wonder what SAS flowers this mower will cut next under the pretext of cutting weeds.
Best
Paul D.
Hi @SASKiwi:
Have you read any of my papers on the subject? For example:
https://support.sas.com/resources/papers/proceedings09/010-2009.pdf
I'm not sure this was the latest but it should suffice.
One real-life use case (from my own experience) is described on page 17. As I recall, in that case using the APP function to move the data in blocks instead of one array item at a time resulted in the reduction of CPU time usage (which mattered since it was on the mainframe, and CPU time usage meant a lot of moolah) by about two orders of magnitude [sic].
I'd also add that using these functions is quite paramount in "character" bitmap search from the standpoint of performance if one wants to use every bit of the bitmap to reduce memory footprint (with a "numeric" bitmap, only the mantissa of each numeric array item can be used, i.e. 53 or 56 out of 64 bits, depending on the OS). If you have time and inspiration, you can find why here:
https://support.sas.com/resources/papers/proceedings19/3101-2019.pdf
on page 13 and on.
Kind regards
Paul D.
Thanks so much @hashman ! Always good to gain insights into the many and varied ways SAS can be used.
Hey @SASKiwi
On of my personal favourite use case is expanding string into an array:
data _null_;
string = "A1B2C3";
array a[6] $ 1;
call POKELONG(string, ADDRLONG(a[1]));
put _all_;
run;
The other one I've been using was when I was showing to my students that you can declare an array pointing multiple times to the same variables. I was showing that subsequent array elements pointing the same addresses:
data _null_;
x=1; y=2;
array a[*] x y x y;
do i=1 to dim(a);
addr = addrlong(a[i]);
put addr= hex16.;
end;
run;
Third one was for reversing order of rows in a 2-dimensional array:
%macro prt(a);
n=dim1(&a.)*8;
do i=1 to dim1(&a.);
call POKELONG(PEEKCLONG(ADDRLONG(&a.[i,1]),n)
,ADDRLONG(print[1])
);
put (print:) (+1 z3.0-R); drop print:;
end;
put;
%mend prt;
%macro swapRows(a,i,j);
n=dim1(&a.)*8; drop i j n;
i=&i.; j=&j.;
call POKELONG(PEEKCLONG(ADDRLONG(&a.[i,1]),n)
,ADDRLONG(tmp[1]));
call POKELONG(PEEKCLONG(ADDRLONG(&a.[j,1]),n)
,ADDRLONG(&a.[i,1]));
call POKELONG(PEEKCLONG(ADDRLONG(tmp[1]),n)
,ADDRLONG(&a.[j,1]));
%mend swapRows;
options ls=max ps=max;
data _null_;
array a[20,20] (1:400);
array tmp[20] _temporary_;
array print[20];
%prt(a);
%swapRows(a,1,20) /* swap row 1 and 20, etc. */
%swapRows(a,2,19)
%swapRows(a,3,18)
%swapRows(a,4,17)
%swapRows(a,5,16)
%swapRows(a,6,15)
%swapRows(a,7,14)
%swapRows(a,8,13)
%swapRows(a,9,12)
%swapRows(a,10,11)
%prt(a);
run;
BTW. printing 2-dim array to the also is easier(only 1 loop) and faster.
Bart
@yabwon - Thanks so much for the valuable insights!
It feels like "something happened" and SAS overreacted. Backward compatibility was imho always an important selling point for SAS. I believe that it would have been more than sufficient for these functions to be disabled as a default but with some option to enable them - something similar to noxcmd.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.