Call: +44 (0)1904 557620 Call
Blog

Pete Finnigan's Oracle Security Weblog

This is the weblog for Pete Finnigan. Pete works in the area of Oracle security and he specialises in auditing Oracle databases for security issues. This weblog is aimed squarely at those interested in the security of their Oracle databases.

[Previous entry: "Extreme PL/SQL"]

Can we Add C Style Pointers to PL/SQL?

In my last blog on Extreme PL/SQL I mentioned pointers in PL/SQL.

PL/SQL does not support pointers or dynamic memory management in the same way that we can write in C code.

In C code we can define a variable as a pointer, allocate some memory and then store a value at the location allocated and pointed to by the pointer. We can then do memory arithmetic or store a different value or free the memory after use so that it can be used elsewhere. Parts of a C program illustrating this are here:

...
int *p; /* define a pointer */
p=(int*)malloc(sizeof(int)*1); /* allocate one integer and assign to the pointer */
*p=7; /* assign a value of 7 stored in the memory located allocated */
...

C has syntax to define a variable as a pointer and access the "contents" of that variable or access the address stored in the variable.

I want to do a similar thing with PL/SQL in my CPU virtual machine implementation so that I can store the programs and use the memory in a similar way to a CPU; to do that in PL/SQL I wanted to access that memory using pointers. I want to show you an earlier version of this idea here to show that we can add and use pointers in PL/SQL.

If we consider what C is doing we can see that the same is easily possible in PL/SQL. In C we allocated blocks of memory from the HEAP or the STACK and we use pointers to perform address arithmetic and then use these pointers to store data at the locations "pointed to" by the pointer.

So here is a sample program that uses a HEAP and pointers to access and manage that memory:

declare
-- -------------------------------------------------------------
-- types
-- -------------------------------------------------------------
type heap_t is table of integer index by binary_integer;
subtype "* number" is integer;
-- -------------------------------------------------------------
-- variables
-- -------------------------------------------------------------
ptr "* number";
val integer;
"*" heap_t;
-- -------------------------------------------------------------
-- functions
-- -------------------------------------------------------------
function malloc(s in number) return "* number"
is
n binary_integer:=1;
begin
if("*".exists(n)) then
n:="*"(n);
while("*".exists(n)) loop
n:="*"(n);
end loop;
return(n+1);
else
"*"(n):=3;
return(n);
end if;
end;
--
function "^"(p in binary_integer) return integer
is
begin
return("*"(p));
end;
--
begin
-- ---------------------------------------------------------------
-- Malloc 1 integer on the heap, assign 7 to it, retrieve its
-- value from the heap
-- ---------------------------------------------------------------
ptr:=malloc(1);
"*"(ptr):=7;
val:="^"(ptr);
dbms_output.put_line('val=['||val||']');
-- ---------------------------------------------------------------
-- Malloc another 1 integer on the heap, assign 9 to it, retrieve
-- its value from the heap
-- ---------------------------------------------------------------
ptr:=malloc(1);
"*"(ptr):=9;
val:="^"(ptr);
dbms_output.put_line('val=['||val||']');
end;
/

We can see that I use syntax similar to C. First we create a HEAP (an area of memory) . We declare a new subtype to be "* integer" - a pointer to an integer. We create an instance of our HEAP and call it "*" so that we can access it in a similar syntax to C. Our Malloc function manages the HEAP. It keeps a simple linked list to point to the next free location of memory and allocate a pointer to that memory for the caller and pass it back. The "^" function allows us to use similar syntax to C to access the contents of the pointer. We can then use the pointers, HEAP and functions to write pointer based code as we would in C.

The simple demo in the begin/end block shows that we use our pointer "ptr" declared above as type "* integer", i.e. a pointer to an integer. We call malloc() to get one byte of storage and assign that one byte of storage address to "ptr". We can then store the digit "7" at the location pointed to by "ptr" in a similar way as we would in C. Finally we can retrieve the contents of the location pointed at by "ptr" and print it out. Then we repeat for a second location and store 9 at that location.

Of course we "deliberately" made a C programmers error and overwrote the "ptr" with a new location and lost the pointer to the first location.

We also need to implement free() to give back the memory to the HEAP after we finished using it.

The storage is not efficient for single integers as we need two integers for each integer used so that the memory management linked list works.

Is there a security issue if we introduce pointers and memory management to PL/SQL, Not in the same sense as a C program as any heap based overflow would not overflow beyond the PL/SQL implementation of the HEAP. If we implement a virtual CPU and store programs in the PL/SQL HEAP then yes those programs could overflow their own system but not escape back to overflow PL/SQL

The simple demo I have shown here has been improved already a lot by me for use in my compiler/CPU and I will take about it again in a later blog.

The C like syntax is of course not necessary; I used it here to illustrate that we can do C like programming and hence system level programming in PL/SQL. We can just use normal PL/SQL variables BUT it would be harder to see the beauty of pointers

#oracleace #sym_42 #oracle #security #database #plsql #c #securecode #bufferoverflow #interpreter #compiler #heap #virtualmachine #vm #cpu