Just a small update: there was a problem in BSF4ooRexx850 which got fixed in the refresh at
<https://sourceforge.net/projects/bsf4oorexx/files/GA/BSF4ooRexx-850.20240304-GA/>.
Also, in case of an error that gets reported via Java, only the latest Java exception gets reported,
not the original cause of the exception which may be located in the Rexx script executed. In order
to get at that exception, one can use the public routine ppJavaExceptionChain() from BSF.CLS, like this:
SIGNAL ON SYNTAX ... some Rexx code interacting with Java ... EXIT SYNTAX:
/* in case of an
error */ co=condition('object') /* get all condition information */ say
ppJavaExceptionChain(co)
/* show Java exception chain */ say "---" RAISE PROPAGATE
---
Being able to assign a security manager to a Rexx instance allows one to execute code to analyze or
code from dubious sources on different Rexx interpreter instances having different security managers
assigned to them. One thing one needs to be aware of is the effect of the assign security managers
on any code being executed on that Rexx interpreter instances.
One can see how easy it is from ooRexx (using BSF4ooRexx850) to create and maintain different Rexx
interpreter instances. This functionality is available to C++ programmers via the ooRexx native APIs
and to Java via BSF4ooRexx850.
---rony
On 16.11.2025 19:39, Rony G. Flatscher wrote:
applied your patch and wrote a little BSF4ooRexx program that would use ooRexx rather than Java to
create four Rexx interpreter instances (RII) and have a simple program run that would display the
Rexx interpreter instance, the thread, and the invocation number. Each RII gets stored in an
array. (BSF4ooRexx allows one to use ooRexx instead of Java, hence a pure ooRexx sample that still
uses Java.)
Then it would create an array with four entries: a title (kind of security manager), and an
instance of the manager. Then it would loop over this array, fetch the RII stored at that index,
use the title and the manager as arguments for the Rexx program stored in the "superviseCode"
resource.
The superviseCode would:
* set the interpreter to the supplied manager
* calls "agent.rex"
* then creates a routine object from the "agent.rex" code and calls it
* then assigns the same manager to the routine object and calls it
Running the program leads to the following observations :
* With the "monitor" manager (on RII 1) it seems that there is a problem when
the LOCAL
checkpoint causes the LOCAL message to be sent as then the control stack gets
full ("Error
11.1: Insufficient control stack space; cannot continue execution."), as if
some sort of
recursion takes place in the LOCAL checkpoint.
* The "noWay" manager (on RII 2) will create "Error 98.948: Authorization
failure: LOCAL
blocked by Security manager.". The supervised program "agent.rex" would
probably have the CALL
checkpoint evalutated first, not the LOCAL checkpoint, so it seems that
error 98.948 is
correct, but for the wrong checkpoint.
* The "replacer" manager (on RII 3) will run without error. If, however, one
uses an
environment symbol in the LOCAL method, then the stack gets full and "Error
11.1: Insufficient
control stack space; cannot continue execution." gets raised.
* The "normal" mode (on RII 4) would run the setSecurityManager for the
interpreter with
argument .nil (assuming that this will be OREF_NULL doing no harm) and not
assign a security
manager to the created routine object then. However there would be an error:
... cut ...
=> caused by: "javax.script.ScriptException:
org.rexxla.bsf.engines.rexx.RexxException:
BSF4ooRexx850/routine/jniRexxSendMessag
eToRexxObject(), error 5:
Rexx traceback line not available from the Rexx condition object (Rexx
condition may have been
caused by a call or message from Java to
Rexx)
Error 97 running line n/a: Object method not found.
Error 97.1: Object "The NIL object" does not understand message "LOCAL"."
... cut ...
At one point in time I could get a crash and a Java hs_err_pid*.log file with a stack trace which
might be helpful therefore I supply it at the very end.
Here first the code for "agent.rex", then "allSecurityManagers.cls", and then the program
"testJLFsecurityManager.rxj" which uses BSF4ooRexx850 (allowing one to use ooRexx instead of Java
which gets exploited here) get depicted, followed by the output of
running "testJLFsecurityManager.rxj", followed by the hs_err_pid*.log file's content.
HTH
---rony
"agent.rex"
/* agent.rex, cf. rexxref.pdf, "Chapter 13. The Security Manager */ "echo Hello
There" -- a
command call rxfuncadd "rxcalcsqrt", "rxmath", "rxcalcsqrt" -- external function say
"result:"
result -- access a variable call syssleep 0.5 -- external call call nixi
line =
linein("./profile") -- access stream BIF say .error -- access .local say
.methods -- access
.environment .json~define("") -- access .environment t = .test~new -- access
.context~package~local t~hello -- access an unprotected method
t~myProtectedMethod -- access
protected method ::requires json.cls -- about to require ::class test -- a
Test class ::method
"myProtectedMethod" protected -- can be supervised say self": method named"
.context~name
::method "hello" -- cannot be supervised say self": hello!"
"allSecurityManagers.cls"
::class MonitoringSupervisor public ::method unknown -- intercept all
messages use arg
methName, methArgs -- say .line":" "in" .context~name "("self")"
infoDir=methArgs[1] -- get
the information directory call show methName,infoDir -- return .true -- let
runtime execute
operation return 1 ::routine show use arg name, dir str="" do idx over
dir~allIndexes~sort if
str="" then str= idx"='"dir[idx]"'" else str=str"," idx"='"dir[idx]"'" end say
"checkpoint"
left('"'name'" ',13,".") str ::class NoWaySupervisor PUBLIC -- A closed
cell Security Manager
blocking all requests ::method unknown -- unknown will trap all Security
Manager checkpoints
-- raise an error for each checkpoint -- say .line":" "in" .context~name
"("self")" raise
syntax 98.948 array(arg(1) "blocked by Security manager") -- cf.
rexxref.pdf, Security
Manager, "13.1.1 Example" ::class ReplacerSupervisor PUBLIC ::method CALL
-- external CALL
checkpoint use arg info -- fetch info directory say .line":" "in" .context~name
"("self")"
info~result = "blocked" -- supply result -- return .true -- .false -- we
handled this return 1
::method COMMAND -- COMMAND checkpoint use arg info -- fetch info directory -- say
.line":"
"in" .context~name "("self")" info~rc = 1234 -- replace the command return
code info~failure =
.true -- raise a FAILURE condition -- return .true -- we handled this
return 1 ::method
ENVIRONMENT -- .ENVIRONMENT lookup checkpoint -- say .line":" "in" .context~name
"("self")" --
return .false -- we handled this, but no result return 0 ::method LOCAL --
.LOCAL lookup
checkpoint -- IF uncommenting the following line a "... line 48: Control
stack full. -- Error
11.1: Insufficient control stack space; cannot continue execution." -- gets
raised as if a
recursion occurs accessing LOCAL -- say .line":" "in" .context~name
"("self")" -- return .true
-- .false -- we handled this, but no result return 1 -- .false -- we
handled this, but no
result ::method METHOD -- protected METHOD checkpoint use arg info -- fetch
info directory --
say .line":" "in" .context~name "("self")" info~result = "blocked" --
supply result -- return
.false -- we handled this return 0 -- we handled this ::method REQUIRES --
REQUIRES checkpoint
use arg info -- fetch info directory -- say .line":" "in" .context~name
"("self")" info~name =
"someOtherPackage.cls" info~securitymanager = self -- use this security
manager -- return
.true -- we handled this, but proceed return 1 -- we handled this, but
proceed ::method STREAM
-- STREAM checkpoint use arg info -- fetch info directory -- say .line":"
"in" .context~name
"("self")" -- always replace with a different stream info~stream =
.stream~new("nixiNoxi.txt")
-- return .true -- we handled this, but proceed return 1 -- we handled
this, but proceed
"testJLFsecurityManager.rxj"
rexxEngines=.array~new -- create three Rexx engines (Rexx interpreter
instances) -- Java
creates one engine of a type per scriptEngineManager (SEM), hence -- we
need to create new
scriptEngineManagers in order to create -- separate Rexx interpreter
instances (RII) do i=1 to
4 re=.BSF~new("javax.script.ScriptEngineManager")~getEngineByName("rexx")
rexxEngines~append(re) rexxCode="a='[R'.context~interpreter']
[T'.context~thread']
[I'.context~invocation']';say 'RE # "i"' a; return a;" re~eval(rexxCode) end
managers=(.MonitoringSupervisor~new, .NoWaySupervisor~new,
.ReplacerSupervisor~new) -- title:
security manager/supervisor argumentArray=.array~of( ('monitor' ,
managers[1]), - ('noWay' ,
managers[2]), - ('replacer', managers[3]), - ('normal' , .nil )) say
superviseCode=.resources~superviseCode~makeString sc =
.bsf~new("javax.script.SimpleScriptContext") do i=1 to argumentArray~items
re=rexxEngines~at(i) -- fetch Rexx interpreter instance
args1=argumentArray[i]
args2=bsf.createJavaArrayOf("java.lang.Object", args1[1], args1[2])
sc~setAttribute(re~ARGV,args2,sc~ENGINE_SCOPE) -- re~eval(supervisecode,sc)
call testCode re,
supervisecode, sc say "="~copies(79) end ::routine testCode signal on
syntax use strict arg
re, code, sc re~eval(code,sc) return syntax: co=condition('o') say
"co~condition:"
co~condition say "co~description:" co~description say "co~additional:" co~additional
say "---"
return ::requires "BSF.CLS" -- get ooRexx-Java bridge ::requires
"allSecurityManagers.cls"
::resource superviseCode use arg title,manager say "title:" title say
"assign security
manager:" setSecurityManager(manager) pgm = 'agent.rex' -- the program to
supervise call (pgm)
say "---" say "now creating a routine object from" pp(pgm)
s=.stream~new(pgm)~~open('read')
r=.routine~new("agent.recks", s~arrayin) s~close say "r~call:" r~call if
title<>"normal" then
do say "--- now assigning the" title "security manager ..."
r~setSecurityManager(manager) say
"r~call:" end say "---" say
::END
output of running "testJLFsecurityManager.rxj":
E:\WU\Lehrveranstaltungen\Materialien\BP1_AutoWin\090_ooRexx_advanced_code\securityManager\jlf>*rexx
testJLFsecurityManager.rxj* REXXout>RE # 1 [R1] [T1] [I1] REXXout>RE # 2
[R2] [T1] [I2]
REXXout>RE # 3 [R3] [T1] [I3] REXXout>RE # 4 [R4] [T1] [I4] *REXXout>title:
monitor*
co~condition: SYNTAX co~description: co~additional:
BSF4ooRexx850/routine/BSF(), error 3: Java
exception occurred: [org.apache.bsf.BSFException: BSF4ooRexx subfunction "inv
oke": bean:
[org.rexxla.bsf.engines.rexx.RexxScriptEngine@123a439b] --> type:
<org.rexxla.bsf.engines.rexx.RexxScriptEngine> method: [EVAL] not found or
execution error! ->
check method name=[EVAL] (caseless o.k., but correct spelling?) -> check
supplied arguments
(correct number, correct types?): arg # 1: Rexx argument=[ use arg title,manager say
"title:"
title say "assign sec...] --> Java value=" use arg title,manager say
"title:" title say
"assign sec..." type=<java.lang.String> arg # 2: Rexx
argument=[javax.script.SimpleScriptContext@27abe2cd] --> Java
value="javax.script.SimpleScriptContext@27a be2cd"
type=<javax.script.SimpleScriptContext> =>
caused by: "javax.script.ScriptException:
org.rexxla.bsf.engines.rexx.RexxException:
BSF4ooRexx850/routine/jniRexxSendMessag eToRexxObject(), error 5: 6 *-*
infoDir=methArgs[1] --
get the information directory Error 11 running C:\Program
Files\BSF4ooRexx850\BSF.CLS line
5095: Control stack full. *Error 11.1: Insufficient control stack space;
cannot continue
execution." ]* org.apache.bsf.BSFException@5fe5c6f ---
===============================================================================
... cut ...
_______________________________________________
Oorexx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-devel