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

Reply via email to