[squeak-dev] Mirror primitives [Was The better debugger support by extending an Object protocol]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Mirror primitives [Was The better debugger support by extending an Object protocol]

Eliot Miranda-2
Hi Igor,

On Mon, Sep 7, 2009 at 10:29 AM, Igor Stasenko <[hidden email]> wrote:

>
> 2009/9/7 Bert Freudenberg <[hidden email]>:
> >
> > On 07.09.2009, at 18:40, Randal L. Schwartz wrote:
> >
> >>>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:
> >>
> >> Igor> Here is the default implementation of
> >>
> >> Object> debugPrintOn: aStream
> >> Igor>   ^ self printOn: aStream
> >>
> >> I like it, but I don't like the name.  It conjurs up the idea of debugging
> >> the #printOn: method itself.
> >>
> >> maybe #printForDebuggerOn: ?
> >
> >
> > It matches the other methods like #longPrintOn: though.
> >
> > Also that would imply only the debugger invokes it, when it's clearly
> > appropriate for any purpose.
> >
> > However, apart from this bike shedding ;) do others think it's a good idea
> > in general? IMHO #printOn: is primarily used for debugging anyway so I
> > wouldn't really expect a separate debug print method to be needed. Debugging
> > transparent proxies isn't for the faint-of-heart anyway, so these developers
> > can adapt their tools and proxies I would guess. OTOH there is precedence in
> > e.g. #asExplorerString, which exists solely to get rid of the quotes
> > enclosing strings for aesthetic reasons ...
> >
>
> I agree with you Bert, that we should consider if its really necessary.
> While #printOn: is used by most code for debugging, some of the code
> using it to serialize object to textual stream, so the #printOn: usage
> is much more generic than just debugging.
>
> As for debugging the transparent proxies - yes you can make own
> tools.. but this means reimplementing/hacking
> other tools , like debugger, inspector and so on, which will probably
> end up with similar solution to what i proposing.
>
> For example, there was a point of discrepancy with debugging the code
> which uses Magma.
> The magma forwarding proxy reifying the object once the first real
> message is sent to it.
> And the problem with such a proxy, that you can't use them in certain
> situations, like:
>
> self perform: aSelectorProxied with: #foo
>
> because #perform doesn't sends the messages to aSelectorProxied and
> primitive fails. But then, when you entering the debugger and trying
> to figure out why its not working - a proxy becomes a real object when
> it printed out.. and so you can't debug the error using debugger.
> Which leaves you to wonder, why code works in debugger, but not
> working at run time :)
I have fixes for this integrated in Qwaq.  This is work I did for
VisualWorks a while back.  The idea is to add a set of mirror
primitives, so called because they do reflection, to ContextPart.
These primitives implement the basic operations of the object model
needed for execution simulation, fetching an object's class, accessing
its named and indexed instance variables, and the number of indexed
instance variables, sending a message, but they take the object
operated on as a parameter and so do function without sending messages
to that object.  These primitives are then used by the execution
simulation machinery to correctly simulate the execution of the
virtual machine irrespective of the class and/or messages implemented
by the receiver.

For example, (eschewing HTML for Bert's contentment)

ContextPart methods for mirror primitives
object: anObject instVarAt: anIndex
        "Primitive. Answer a fixed variable in an object. The numbering of the
         variables corresponds to the named instance variables. Fail if the index
         is not an Integer or is not the index of a fixed variable. Essential for the
         debugger. See  Object documentation whatIsAPrimitive."

        <primitive: 73>
        "Access beyond fixed variables."
        ^self object: anObject basicAt: anIndex - (self objectClass: anObject) instSize

object: anObject instVarAt: anIndex put: aValue
        "Primitive. Store a value into a fixed variable in the argument anObject.
         The numbering of the variables corresponds to the named instance
         variables.  Fail if the index is not an Integer or is not the index of a
         fixed variable.  Answer the value stored as the result. Using this
         message violates the  principle that each object has sovereign control
         over the storing of values into its instance variables. Essential for the
         debugger. See Object documentation whatIsAPrimitive."

        <primitive: 74>
        "Access beyond fixed fields"
        ^self object: anObject basicAt: anIndex - (self objectClass:
anObject) instSize put: aValue

ContextPart methods for instruction decoding
pushReceiverVariable: offset
        "Simulate the action of bytecode that pushes the contents of the receiver's
        instance variable whose index is the argument, index, on the top of the stack."

        self push: (self object: self receiver instVarAt: offset + 1)

popIntoReceiverVariable: offset
        "Simulate the action of bytecode that removes the top of the stack and
        stores it into an instance variable of my receiver."

        self object: self receiver instVarAt: offset + 1 put: self pop

storeIntoReceiverVariable: offset
        "Simulate the action of bytecode that stores the top of the stack into an
        instance variable of my receiver."

        self object: self receiver instVarAt: offset + 1 put: self top

The attached change set for the image level code is also conflated
with changes that allow the debugger to set the primitive error code
correctly.


The VM also needs to implement the primitives.  If the order of the
arguments are the same as those of the corresponding non-reflective
primitive (e.g. aContext object: theReceiver instVarAt: index put:
value has the same order as theReceiver instVarAt: index put: value)
and the primitive pops back the stack using self pop: argumentCount +
1, one can use the same VM primitive implementations as the
non-reflective ones and so avoid needing extra primitives.

However, not all primitives are correctly implemented; e.g. at: and
at:put: are, but size is not.  So before we can use this there is some
work to do in the standard VMs.  I'm attaching here the implementation
in the Stack VM which will require some back porting to the standard
VM.  None of these changes has performance implications because the
special selector impelmentations of at: at:put: size and #== are not
affected.

With the above changes one can safely step through code that uses
proxies that do not inherit from Object, or even ProtoObject.  I still
need to implement a PrimitiveObjectInspector, or use the mirror
primitives in implementing the Inspector.  However, there is one more
important thing needed in the debugger which these changes do not
address and that is the value of Processor activeProcess within  the
debugger.  e.g. "print it" the following:

| thisProcessOutsideTheDebugger thisProcessInsideTheDebugger |
thisProcessOutsideTheDebugger := Processor activeProcess.
self halt.
thisProcessInsideTheDebugger := Processor activeProcess.
'Send to here (Into) then proceed'.
thisProcessOutsideTheDebugger == thisProcessInsideTheDebugger

This will potentially break debugging of servers that maintain process
pools.  Andreas has proposed a very simple fix for this.  Add an
instance variable to Process called, e.g. effectiveProcess, which is
nil in normal processes.  When the debugger runs it sets
effectiveProcess to that of the process which it is debugging and
Processor activeProcess is implemented as something like

ProcessorScheduler methods for accessing
activeProcess
    ^activeProcess effectiveProcess ifNil: [activeProcess]

I'll try and get round to this soon.


I'm posting this rather than integrating because a) the VMs need to
get updated before we can use the image level code and, b) the VM
folks need code to test their VMs with.  I'm happy to integrate the
image-level changes once the VMs have been upgraded.

best
Eliot

>
> >
> > - Bert -
> >
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



MirrorPrimitives.st (32K) Download Attachment
MirrorPrimitivesVM.st (14K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Bert Freudenberg
On 07.09.2009, at 20:56, Eliot Miranda wrote:

>
> I have fixes for this integrated in Qwaq.  This is work I did for
> VisualWorks a while back.  The idea is to add a set of mirror
> primitives, so called because they do reflection, to ContextPart.
> These primitives implement the basic operations of the object model
> needed for execution simulation, fetching an object's class, accessing
> its named and indexed instance variables, and the number of indexed
> instance variables, sending a message, but they take the object
> operated on as a parameter and so do function without sending messages
> to that object.

Wouldn't that break encapsulation in a way we never had to before?

- Bert -



Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Mirror primitives [Was The better debugger support by extending an Object protocol]

Eliot Miranda-2
In reply to this post by Eliot Miranda-2
On Mon, Sep 7, 2009 at 11:56 AM, Eliot Miranda<[hidden email]> wrote:

> Hi Igor,
>
> On Mon, Sep 7, 2009 at 10:29 AM, Igor Stasenko <[hidden email]> wrote:
>>
>> 2009/9/7 Bert Freudenberg <[hidden email]>:
>> >
>> > On 07.09.2009, at 18:40, Randal L. Schwartz wrote:
>> >
>> >>>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:
>> >>
>> >> Igor> Here is the default implementation of
>> >>
>> >> Object> debugPrintOn: aStream
>> >> Igor>   ^ self printOn: aStream
>> >>
>> >> I like it, but I don't like the name.  It conjurs up the idea of debugging
>> >> the #printOn: method itself.
>> >>
>> >> maybe #printForDebuggerOn: ?
>> >
>> >
>> > It matches the other methods like #longPrintOn: though.
>> >
>> > Also that would imply only the debugger invokes it, when it's clearly
>> > appropriate for any purpose.
>> >
>> > However, apart from this bike shedding ;) do others think it's a good idea
>> > in general? IMHO #printOn: is primarily used for debugging anyway so I
>> > wouldn't really expect a separate debug print method to be needed. Debugging
>> > transparent proxies isn't for the faint-of-heart anyway, so these developers
>> > can adapt their tools and proxies I would guess. OTOH there is precedence in
>> > e.g. #asExplorerString, which exists solely to get rid of the quotes
>> > enclosing strings for aesthetic reasons ...
>> >
>>
>> I agree with you Bert, that we should consider if its really necessary.
>> While #printOn: is used by most code for debugging, some of the code
>> using it to serialize object to textual stream, so the #printOn: usage
>> is much more generic than just debugging.
>>
>> As for debugging the transparent proxies - yes you can make own
>> tools.. but this means reimplementing/hacking
>> other tools , like debugger, inspector and so on, which will probably
>> end up with similar solution to what i proposing.
>>
>> For example, there was a point of discrepancy with debugging the code
>> which uses Magma.
>> The magma forwarding proxy reifying the object once the first real
>> message is sent to it.
>> And the problem with such a proxy, that you can't use them in certain
>> situations, like:
>>
>> self perform: aSelectorProxied with: #foo
>>
>> because #perform doesn't sends the messages to aSelectorProxied and
>> primitive fails. But then, when you entering the debugger and trying
>> to figure out why its not working - a proxy becomes a real object when
>> it printed out.. and so you can't debug the error using debugger.
>> Which leaves you to wonder, why code works in debugger, but not
>> working at run time :)
>
> I have fixes for this integrated in Qwaq.  This is work I did for
> VisualWorks a while back.  The idea is to add a set of mirror
> primitives, so called because they do reflection, to ContextPart.
> These primitives implement the basic operations of the object model
> needed for execution simulation, fetching an object's class, accessing
> its named and indexed instance variables, and the number of indexed
> instance variables, sending a message, but they take the object
> operated on as a parameter and so do function without sending messages
> to that object.  These primitives are then used by the execution
> simulation machinery to correctly simulate the execution of the
> virtual machine irrespective of the class and/or messages implemented
> by the receiver.
>
> For example, (eschewing HTML for Bert's contentment)
>
> ContextPart methods for mirror primitives
> object: anObject instVarAt: anIndex
>        "Primitive. Answer a fixed variable in an object. The numbering of the
>         variables corresponds to the named instance variables. Fail if the index
>         is not an Integer or is not the index of a fixed variable. Essential for the
>         debugger. See  Object documentation whatIsAPrimitive."
>
>        <primitive: 73>
>        "Access beyond fixed variables."
>        ^self object: anObject basicAt: anIndex - (self objectClass: anObject) instSize
>
> object: anObject instVarAt: anIndex put: aValue
>        "Primitive. Store a value into a fixed variable in the argument anObject.
>         The numbering of the variables corresponds to the named instance
>         variables.  Fail if the index is not an Integer or is not the index of a
>         fixed variable.  Answer the value stored as the result. Using this
>         message violates the  principle that each object has sovereign control
>         over the storing of values into its instance variables. Essential for the
>         debugger. See Object documentation whatIsAPrimitive."
>
>        <primitive: 74>
>        "Access beyond fixed fields"
>        ^self object: anObject basicAt: anIndex - (self objectClass:
> anObject) instSize put: aValue
>
> ContextPart methods for instruction decoding
> pushReceiverVariable: offset
>        "Simulate the action of bytecode that pushes the contents of the receiver's
>        instance variable whose index is the argument, index, on the top of the stack."
>
>        self push: (self object: self receiver instVarAt: offset + 1)
>
> popIntoReceiverVariable: offset
>        "Simulate the action of bytecode that removes the top of the stack and
>        stores it into an instance variable of my receiver."
>
>        self object: self receiver instVarAt: offset + 1 put: self pop
>
> storeIntoReceiverVariable: offset
>        "Simulate the action of bytecode that stores the top of the stack into an
>        instance variable of my receiver."
>
>        self object: self receiver instVarAt: offset + 1 put: self top
>
> The attached change set for the image level code is also conflated
> with changes that allow the debugger to set the primitive error code
> correctly.
>
>
> The VM also needs to implement the primitives.  If the order of the
> arguments are the same as those of the corresponding non-reflective
> primitive (e.g. aContext object: theReceiver instVarAt: index put:
> value has the same order as theReceiver instVarAt: index put: value)
> and the primitive pops back the stack using self pop: argumentCount +
> 1, one can use the same VM primitive implementations as the
> non-reflective ones and so avoid needing extra primitives.
>
> However, not all primitives are correctly implemented; e.g. at: and
> at:put: are, but size is not.  So before we can use this there is some
> work to do in the standard VMs.  I'm attaching here the implementation
> in the Stack VM which will require some back porting to the standard
> VM.  None of these changes has performance implications because the
> special selector impelmentations of at: at:put: size and #== are not
> affected.
>
> With the above changes one can safely step through code that uses
> proxies that do not inherit from Object, or even ProtoObject.  I still
> need to implement a PrimitiveObjectInspector, or use the mirror
> primitives in implementing the Inspector.  However, there is one more
> important thing needed in the debugger which these changes do not
> address and that is the value of Processor activeProcess within  the
> debugger.  e.g. "print it" the following:
>
> | thisProcessOutsideTheDebugger thisProcessInsideTheDebugger |
> thisProcessOutsideTheDebugger := Processor activeProcess.
> self halt.
> thisProcessInsideTheDebugger := Processor activeProcess.
> 'Send to here (Into) then proceed'.
> thisProcessOutsideTheDebugger == thisProcessInsideTheDebugger
>
> This will potentially break debugging of servers that maintain process
> pools.  Andreas has proposed a very simple fix for this.  Add an
> instance variable to Process called, e.g. effectiveProcess, which is
> nil in normal processes.  When the debugger runs it sets
> effectiveProcess to that of the process which it is debugging and
> Processor activeProcess is implemented as something like
>
> ProcessorScheduler methods for accessing
> activeProcess
>    ^activeProcess effectiveProcess ifNil: [activeProcess]
>
> I'll try and get round to this soon.
That appeared to be very easy, because the debugger is well-factored,
deferring to its interruptedProcess for all execution.  care to bang
on the attached?  The definition of process is probably wrong for your
image so integrate that carefully.


>
>
> I'm posting this rather than integrating because a) the VMs need to
> get updated before we can use the image level code and, b) the VM
> folks need code to test their VMs with.  I'm happy to integrate the
> image-level changes once the VMs have been upgraded.
>
> best
> Eliot
>
>>
>> >
>> > - Bert -
>> >
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>



effectiveProcess.st (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Eliot Miranda-2
In reply to this post by Bert Freudenberg
On Mon, Sep 7, 2009 at 12:19 PM, Bert Freudenberg<[hidden email]> wrote:

> On 07.09.2009, at 20:56, Eliot Miranda wrote:
>>
>> I have fixes for this integrated in Qwaq.  This is work I did for
>> VisualWorks a while back.  The idea is to add a set of mirror
>> primitives, so called because they do reflection, to ContextPart.
>> These primitives implement the basic operations of the object model
>> needed for execution simulation, fetching an object's class, accessing
>> its named and indexed instance variables, and the number of indexed
>> instance variables, sending a message, but they take the object
>> operated on as a parameter and so do function without sending messages
>> to that object.
>
> Wouldn't that break encapsulation in a way we never had to before?

If one dared use those primitives for anything other than simulating
the VM then I suppose they're a little worse than instVarAt:put: and
basicAt:put:, but not so much.  I think it is much more dangerous to
have a debugger that appears to be correct but breaks one's code in
ways that are horribly difficult to understand.

Note that both Self and Newspeak (and VisualWorks) take the mirror
primitive approach.  But there is certainly a security issue and one
wants to medate access to the mirror primitives carefully.

>
> - Bert -
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Bert Freudenberg

On 07.09.2009, at 21:29, Eliot Miranda wrote:

> On Mon, Sep 7, 2009 at 12:19 PM, Bert  
> Freudenberg<[hidden email]> wrote:
>> On 07.09.2009, at 20:56, Eliot Miranda wrote:
>>>
>>> I have fixes for this integrated in Qwaq.  This is work I did for
>>> VisualWorks a while back.  The idea is to add a set of mirror
>>> primitives, so called because they do reflection, to ContextPart.
>>> These primitives implement the basic operations of the object model
>>> needed for execution simulation, fetching an object's class,  
>>> accessing
>>> its named and indexed instance variables, and the number of indexed
>>> instance variables, sending a message, but they take the object
>>> operated on as a parameter and so do function without sending  
>>> messages
>>> to that object.
>>
>> Wouldn't that break encapsulation in a way we never had to before?
>
> If one dared use those primitives for anything other than simulating
> the VM then I suppose they're a little worse than instVarAt:put: and
> basicAt:put:, but not so much.

These are fundamentally different. #instVarAt:put: and basicAt:put:  
are regular methods that an object itself implements to give others  
access to its internal state. It can very well chose not to.

>  I think it is much more dangerous to
> have a debugger that appears to be correct but breaks one's code in
> ways that are horribly difficult to understand.
>
> Note that both Self and Newspeak (and VisualWorks) take the mirror
> primitive approach.  But there is certainly a security issue and one
> wants to medate access to the mirror primitives carefully.


Alas we have no way for restricting access in Squeak.

Anyway, these primitives are useful for debugging indeed. How about  
disabling them in production mode?

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Eliot Miranda-2
On Mon, Sep 7, 2009 at 12:34 PM, Bert Freudenberg<[hidden email]> wrote:

>
> On 07.09.2009, at 21:29, Eliot Miranda wrote:
>
>> On Mon, Sep 7, 2009 at 12:19 PM, Bert Freudenberg<[hidden email]>
>> wrote:
>>>
>>> On 07.09.2009, at 20:56, Eliot Miranda wrote:
>>>>
>>>> I have fixes for this integrated in Qwaq.  This is work I did for
>>>> VisualWorks a while back.  The idea is to add a set of mirror
>>>> primitives, so called because they do reflection, to ContextPart.
>>>> These primitives implement the basic operations of the object model
>>>> needed for execution simulation, fetching an object's class, accessing
>>>> its named and indexed instance variables, and the number of indexed
>>>> instance variables, sending a message, but they take the object
>>>> operated on as a parameter and so do function without sending messages
>>>> to that object.
>>>
>>> Wouldn't that break encapsulation in a way we never had to before?
>>
>> If one dared use those primitives for anything other than simulating
>> the VM then I suppose they're a little worse than instVarAt:put: and
>> basicAt:put:, but not so much.
>
> These are fundamentally different. #instVarAt:put: and basicAt:put: are
> regular methods that an object itself implements to give others access to
> its internal state. It can very well chose not to.

Yes, but they are implemented in Object and potentially defeat
encapsulation on every object in the system that inherits from it
(which is almost all).  In practice this isn't an issue because they
are not abused.  Its the same with the mirror primitives.  So while it
appears the sky can fall in a new way it doesn't.

>
>>  I think it is much more dangerous to
>> have a debugger that appears to be correct but breaks one's code in
>> ways that are horribly difficult to understand.
>>
>> Note that both Self and Newspeak (and VisualWorks) take the mirror
>> primitive approach.  But there is certainly a security issue and one
>> wants to medate access to the mirror primitives carefully.
>
>
> Alas we have no way for restricting access in Squeak.

I can imagine a way using withArgs:evaluate:.  Compile the methods,
save them in class variables of ContextPart and access them through a
checking interface that only allows their execution in the context of
the debugger.  But I still think this is overkill.  What, in Squeak,
is to stop one compiling a method on ProtoObject and using it to
subvert encapsulation on all objects?  Nothing.  So the issue of
security is not made any worse by the introduction of the mirror
primitives, but the debugger is enhanced significantly.  So for me
they're a clear win.


>
> Anyway, these primitives are useful for debugging indeed. How about
> disabling them in production mode?

Alas the process termination code uses execution simulation to
terminate suspended processes and that means using the mirror
primitives to safely terminate processes.  The current non-mirror
implementation could conceivably screw up terminating processes
executing code on encapsulators.

I think a better way is to propose a security mechanism that prevents
their abuse.  Any ideas?

>
> - Bert -
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Igor Stasenko
>From VM's perspective , all object are just a state holders, with slots and
determined size(s).
In language environment, however, the objects are treated as a
black-boxes to which you can
send the messages only.
The debugger is staying somewhere in the middle, i.e. it should know
how to connect these two realms
in order to simulate VM-specific behavior when you stepping over the code.
So, for the means of debugging i tend to agree that mirror prims will
be quite useful.
But same as Bert i don't want to see these prims abused by people who
bypassing the 'black-box' paradigm
by using them, so we ending up with a 'static-type-oriented' C-like
programming instead of object oriented one.

2009/9/7 Eliot Miranda <[hidden email]>:

> On Mon, Sep 7, 2009 at 12:34 PM, Bert Freudenberg<[hidden email]> wrote:
>>
>> On 07.09.2009, at 21:29, Eliot Miranda wrote:
>>
>>> On Mon, Sep 7, 2009 at 12:19 PM, Bert Freudenberg<[hidden email]>
>>> wrote:
>>>>
>>>> On 07.09.2009, at 20:56, Eliot Miranda wrote:
>>>>>
>>>>> I have fixes for this integrated in Qwaq.  This is work I did for
>>>>> VisualWorks a while back.  The idea is to add a set of mirror
>>>>> primitives, so called because they do reflection, to ContextPart.
>>>>> These primitives implement the basic operations of the object model
>>>>> needed for execution simulation, fetching an object's class, accessing
>>>>> its named and indexed instance variables, and the number of indexed
>>>>> instance variables, sending a message, but they take the object
>>>>> operated on as a parameter and so do function without sending messages
>>>>> to that object.
>>>>
>>>> Wouldn't that break encapsulation in a way we never had to before?
>>>
>>> If one dared use those primitives for anything other than simulating
>>> the VM then I suppose they're a little worse than instVarAt:put: and
>>> basicAt:put:, but not so much.
>>
>> These are fundamentally different. #instVarAt:put: and basicAt:put: are
>> regular methods that an object itself implements to give others access to
>> its internal state. It can very well chose not to.
>
> Yes, but they are implemented in Object and potentially defeat
> encapsulation on every object in the system that inherits from it
> (which is almost all).  In practice this isn't an issue because they
> are not abused.  Its the same with the mirror primitives.  So while it
> appears the sky can fall in a new way it doesn't.
>
>>
>>>  I think it is much more dangerous to
>>> have a debugger that appears to be correct but breaks one's code in
>>> ways that are horribly difficult to understand.
>>>
>>> Note that both Self and Newspeak (and VisualWorks) take the mirror
>>> primitive approach.  But there is certainly a security issue and one
>>> wants to medate access to the mirror primitives carefully.
>>
>>
>> Alas we have no way for restricting access in Squeak.
>
> I can imagine a way using withArgs:evaluate:.  Compile the methods,
> save them in class variables of ContextPart and access them through a
> checking interface that only allows their execution in the context of
> the debugger.  But I still think this is overkill.  What, in Squeak,
> is to stop one compiling a method on ProtoObject and using it to
> subvert encapsulation on all objects?  Nothing.  So the issue of
> security is not made any worse by the introduction of the mirror
> primitives, but the debugger is enhanced significantly.  So for me
> they're a clear win.
>
>
>>
>> Anyway, these primitives are useful for debugging indeed. How about
>> disabling them in production mode?
>
> Alas the process termination code uses execution simulation to
> terminate suspended processes and that means using the mirror
> primitives to safely terminate processes.  The current non-mirror
> implementation could conceivably screw up terminating processes
> executing code on encapsulators.
>
> I think a better way is to propose a security mechanism that prevents
> their abuse.  Any ideas?
>
>>
>> - Bert -
>>
>>
>>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Eliot Miranda-2
On Mon, Sep 7, 2009 at 1:29 PM, Igor Stasenko<[hidden email]> wrote:

> >From VM's perspective , all object are just a state holders, with slots and
> determined size(s).
> In language environment, however, the objects are treated as a
> black-boxes to which you can
> send the messages only.
> The debugger is staying somewhere in the middle, i.e. it should know
> how to connect these two realms
> in order to simulate VM-specific behavior when you stepping over the code.
> So, for the means of debugging i tend to agree that mirror prims will
> be quite useful.
> But same as Bert i don't want to see these prims abused by people who
> bypassing the 'black-box' paradigm
> by using them, so we ending up with a 'static-type-oriented' C-like
> programming instead of object oriented one.

I understand, but the argument is a bit further along than that.  The
question is whether the addition of the mirror primitives makes the
situation significantly worse than it is already with the presence of
instVarAt:put: primitiveChangeClassTo: become: and the compiler.  I
can easily subvert any encapsulation by a class that doesn't inherit
from Object or ProtoObject and doesn't implement instVarAt:put: by
using reflection to enumerate over all classes, and adding the
instVarAt:put: method to all root classes' method dictionaries under a
selector of my choosing.  I can construct a context activation on some
object with a method of my construction and set it running.  I don't
even have to have the compiler for either of these exploits.  The open
meta system is simply not secure.

I argue that therefore adding the mirror primitives does not
materially make the situation any worse than it already is, but does
give one an accurate debugger, and accurate process termination.  I
argue that the mirror primitives are in some sense isomorphic in their
insecurity to the existing meta facilities (such as open access to
thisContext), but that in practice the openness of the meta-system has
not presented a security problem; images and processes are still
sealed, and secure applications which do not allow the import or
execution of arbitrary code can still be deployed even though they
contain apparently insecure code because they do not provide a path
such that externally that unsafe code can be activated, and because
internally those applications do not misuse the
encapsulation-violating facilities such as instVarAt:put:.

I argue that in practice encapsulation is a design convention that
allows one to reason more effectively about complex systems, but that
it is not a hard-and-fast rule, and that breaking encapsulation in
certain stereotypical situations is common and extremely useful, for
example in reconstructing or transporting objects that have been
externalised on some stream.

>
> 2009/9/7 Eliot Miranda <[hidden email]>:
>> On Mon, Sep 7, 2009 at 12:34 PM, Bert Freudenberg<[hidden email]> wrote:
>>>
>>> On 07.09.2009, at 21:29, Eliot Miranda wrote:
>>>
>>>> On Mon, Sep 7, 2009 at 12:19 PM, Bert Freudenberg<[hidden email]>
>>>> wrote:
>>>>>
>>>>> On 07.09.2009, at 20:56, Eliot Miranda wrote:
>>>>>>
>>>>>> I have fixes for this integrated in Qwaq.  This is work I did for
>>>>>> VisualWorks a while back.  The idea is to add a set of mirror
>>>>>> primitives, so called because they do reflection, to ContextPart.
>>>>>> These primitives implement the basic operations of the object model
>>>>>> needed for execution simulation, fetching an object's class, accessing
>>>>>> its named and indexed instance variables, and the number of indexed
>>>>>> instance variables, sending a message, but they take the object
>>>>>> operated on as a parameter and so do function without sending messages
>>>>>> to that object.
>>>>>
>>>>> Wouldn't that break encapsulation in a way we never had to before?
>>>>
>>>> If one dared use those primitives for anything other than simulating
>>>> the VM then I suppose they're a little worse than instVarAt:put: and
>>>> basicAt:put:, but not so much.
>>>
>>> These are fundamentally different. #instVarAt:put: and basicAt:put: are
>>> regular methods that an object itself implements to give others access to
>>> its internal state. It can very well chose not to.
>>
>> Yes, but they are implemented in Object and potentially defeat
>> encapsulation on every object in the system that inherits from it
>> (which is almost all).  In practice this isn't an issue because they
>> are not abused.  Its the same with the mirror primitives.  So while it
>> appears the sky can fall in a new way it doesn't.
>>
>>>
>>>>  I think it is much more dangerous to
>>>> have a debugger that appears to be correct but breaks one's code in
>>>> ways that are horribly difficult to understand.
>>>>
>>>> Note that both Self and Newspeak (and VisualWorks) take the mirror
>>>> primitive approach.  But there is certainly a security issue and one
>>>> wants to medate access to the mirror primitives carefully.
>>>
>>>
>>> Alas we have no way for restricting access in Squeak.
>>
>> I can imagine a way using withArgs:evaluate:.  Compile the methods,
>> save them in class variables of ContextPart and access them through a
>> checking interface that only allows their execution in the context of
>> the debugger.  But I still think this is overkill.  What, in Squeak,
>> is to stop one compiling a method on ProtoObject and using it to
>> subvert encapsulation on all objects?  Nothing.  So the issue of
>> security is not made any worse by the introduction of the mirror
>> primitives, but the debugger is enhanced significantly.  So for me
>> they're a clear win.
>>
>>
>>>
>>> Anyway, these primitives are useful for debugging indeed. How about
>>> disabling them in production mode?
>>
>> Alas the process termination code uses execution simulation to
>> terminate suspended processes and that means using the mirror
>> primitives to safely terminate processes.  The current non-mirror
>> implementation could conceivably screw up terminating processes
>> executing code on encapsulators.
>>
>> I think a better way is to propose a security mechanism that prevents
>> their abuse.  Any ideas?
>>
>>>
>>> - Bert -
>>>
>>>
>>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Colin Putney
In reply to this post by Eliot Miranda-2

On 7-Sep-09, at 1:10 PM, Eliot Miranda wrote:

> I can imagine a way using withArgs:evaluate:.  Compile the methods,
> save them in class variables of ContextPart and access them through a
> checking interface that only allows their execution in the context of
> the debugger.  But I still think this is overkill.  What, in Squeak,
> is to stop one compiling a method on ProtoObject and using it to
> subvert encapsulation on all objects?  Nothing.  So the issue of
> security is not made any worse by the introduction of the mirror
> primitives, but the debugger is enhanced significantly.  So for me
> they're a clear win.

One year at StS I had a discussion with Travis about Trippy. He  
mentioned to me that they had planned to use the mirror primitives for  
Trippy, but ultimately found that it was better to do something  
similar to what you describe above: compile a method that answers an  
instvar then execute with the object as the receiver using the inverse  
of #withArgs:evaluate: something like #valueWithReciever:args: on  
CompiledMethod. This seems like a powerful and flexible approach to  
me. You can do anything the object its self can do with its internal  
state, but completely bypass message dispatch. Best of all there's  
only one primitive required.

Admittedly a debugger involves a bit more than an inspector, but the  
technique would seem to be applicable. Is there some reason that this  
combined with traditional simulation wouldn't work well?

Colin

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Mirror primitives

Andreas.Raab
In reply to this post by Eliot Miranda-2
Eliot Miranda wrote:

> I argue that therefore adding the mirror primitives does not
> materially make the situation any worse than it already is, but does
> give one an accurate debugger, and accurate process termination.  I
> argue that the mirror primitives are in some sense isomorphic in their
> insecurity to the existing meta facilities (such as open access to
> thisContext), but that in practice the openness of the meta-system has
> not presented a security problem; images and processes are still
> sealed, and secure applications which do not allow the import or
> execution of arbitrary code can still be deployed even though they
> contain apparently insecure code because they do not provide a path
> such that externally that unsafe code can be activated, and because
> internally those applications do not misuse the
> encapsulation-violating facilities such as instVarAt:put:.

Not only agreed but I will go one step further by claiming that if
anyone ever tries to build a secure system they will soon find that an
absolutely necessary step is to use mirrors for accessing critical
object/vm state. Reliance on a correct implementation of #basicAt: is
not an option if the objects must be assumed to be hostile.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Eliot Miranda-2
In reply to this post by Colin Putney
On Mon, Sep 7, 2009 at 1:47 PM, Colin Putney<[hidden email]> wrote:

>
> On 7-Sep-09, at 1:10 PM, Eliot Miranda wrote:
>
>> I can imagine a way using withArgs:evaluate:.  Compile the methods,
>> save them in class variables of ContextPart and access them through a
>> checking interface that only allows their execution in the context of
>> the debugger.  But I still think this is overkill.  What, in Squeak,
>> is to stop one compiling a method on ProtoObject and using it to
>> subvert encapsulation on all objects?  Nothing.  So the issue of
>> security is not made any worse by the introduction of the mirror
>> primitives, but the debugger is enhanced significantly.  So for me
>> they're a clear win.
>
> One year at StS I had a discussion with Travis about Trippy. He mentioned to
> me that they had planned to use the mirror primitives for Trippy, but
> ultimately found that it was better to do something similar to what you
> describe above: compile a method that answers an instvar then execute with
> the object as the receiver using the inverse of #withArgs:evaluate:
> something like #valueWithReciever:args: on CompiledMethod. This seems like a
> powerful and flexible approach to me. You can do anything the object its
> self can do with its internal state, but completely bypass message dispatch.
> Best of all there's only one primitive required.

In Squeak valueWithReciever:args: is built upon withArgs:evaluate:.
See my other posts on the holes that valueWithReciever:args: open up.
The VW debugger still uses the mirror primitives so I don't see the
engineering effort to add the alternative path was worth it.

> Admittedly a debugger involves a bit more than an inspector, but the
> technique would seem to be applicable. Is there some reason that this
> combined with traditional simulation wouldn't work well?

In principle, no.  Provided one caches the methods, then there's no
performance issue.  But is it any better?  There's no difference in
security.  The fact that one can implement things either way
demonstrates this.  The security issue is whether the system can work
correctly without facilities analogous to the mirror primitives.  The
implementation of Process>>terminate means that there isn't, because
it uses the execution simulation machinery, and for correctness the
execution simulation machinery needs mechanisms isomorphic to the
mirror primitives, no matter how they are implemented.

I think an implementation which makes it easy to strip out the mirror
primitives when deploying is attractive.  The mirror primitives are
simple to use and understand.  So the thing to focus on is process
termination.  Remove execution simulation from that path and the
system is more secure (if that's important to you).  Keep incorrect
execution simulation in process termination and the system functions
without the mirror primitive hole (but with plenty of others) but is
incorrect w.r.t. processes on encapsulators (if that's important to
you).

>
> Colin
>
>

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Mirror primitives [Was The better debugger support by extending an Object protocol]

Eliot Miranda-2
In reply to this post by Eliot Miranda-2
Oops.  I left out popTo: et al and so Processor activeProcess would be
wrong inside unwind blocks evaluated in the debugger.  So find v2
attached...


On Mon, Sep 7, 2009 at 12:25 PM, Eliot Miranda<[hidden email]> wrote:

> On Mon, Sep 7, 2009 at 11:56 AM, Eliot Miranda<[hidden email]> wrote:
>> Hi Igor,
>>
>> On Mon, Sep 7, 2009 at 10:29 AM, Igor Stasenko <[hidden email]> wrote:
>>>
>>> 2009/9/7 Bert Freudenberg <[hidden email]>:
>>> >
>>> > On 07.09.2009, at 18:40, Randal L. Schwartz wrote:
>>> >
>>> >>>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:
>>> >>
>>> >> Igor> Here is the default implementation of
>>> >>
>>> >> Object> debugPrintOn: aStream
>>> >> Igor>   ^ self printOn: aStream
>>> >>
>>> >> I like it, but I don't like the name.  It conjurs up the idea of debugging
>>> >> the #printOn: method itself.
>>> >>
>>> >> maybe #printForDebuggerOn: ?
>>> >
>>> >
>>> > It matches the other methods like #longPrintOn: though.
>>> >
>>> > Also that would imply only the debugger invokes it, when it's clearly
>>> > appropriate for any purpose.
>>> >
>>> > However, apart from this bike shedding ;) do others think it's a good idea
>>> > in general? IMHO #printOn: is primarily used for debugging anyway so I
>>> > wouldn't really expect a separate debug print method to be needed. Debugging
>>> > transparent proxies isn't for the faint-of-heart anyway, so these developers
>>> > can adapt their tools and proxies I would guess. OTOH there is precedence in
>>> > e.g. #asExplorerString, which exists solely to get rid of the quotes
>>> > enclosing strings for aesthetic reasons ...
>>> >
>>>
>>> I agree with you Bert, that we should consider if its really necessary.
>>> While #printOn: is used by most code for debugging, some of the code
>>> using it to serialize object to textual stream, so the #printOn: usage
>>> is much more generic than just debugging.
>>>
>>> As for debugging the transparent proxies - yes you can make own
>>> tools.. but this means reimplementing/hacking
>>> other tools , like debugger, inspector and so on, which will probably
>>> end up with similar solution to what i proposing.
>>>
>>> For example, there was a point of discrepancy with debugging the code
>>> which uses Magma.
>>> The magma forwarding proxy reifying the object once the first real
>>> message is sent to it.
>>> And the problem with such a proxy, that you can't use them in certain
>>> situations, like:
>>>
>>> self perform: aSelectorProxied with: #foo
>>>
>>> because #perform doesn't sends the messages to aSelectorProxied and
>>> primitive fails. But then, when you entering the debugger and trying
>>> to figure out why its not working - a proxy becomes a real object when
>>> it printed out.. and so you can't debug the error using debugger.
>>> Which leaves you to wonder, why code works in debugger, but not
>>> working at run time :)
>>
>> I have fixes for this integrated in Qwaq.  This is work I did for
>> VisualWorks a while back.  The idea is to add a set of mirror
>> primitives, so called because they do reflection, to ContextPart.
>> These primitives implement the basic operations of the object model
>> needed for execution simulation, fetching an object's class, accessing
>> its named and indexed instance variables, and the number of indexed
>> instance variables, sending a message, but they take the object
>> operated on as a parameter and so do function without sending messages
>> to that object.  These primitives are then used by the execution
>> simulation machinery to correctly simulate the execution of the
>> virtual machine irrespective of the class and/or messages implemented
>> by the receiver.
>>
>> For example, (eschewing HTML for Bert's contentment)
>>
>> ContextPart methods for mirror primitives
>> object: anObject instVarAt: anIndex
>>        "Primitive. Answer a fixed variable in an object. The numbering of the
>>         variables corresponds to the named instance variables. Fail if the index
>>         is not an Integer or is not the index of a fixed variable. Essential for the
>>         debugger. See  Object documentation whatIsAPrimitive."
>>
>>        <primitive: 73>
>>        "Access beyond fixed variables."
>>        ^self object: anObject basicAt: anIndex - (self objectClass: anObject) instSize
>>
>> object: anObject instVarAt: anIndex put: aValue
>>        "Primitive. Store a value into a fixed variable in the argument anObject.
>>         The numbering of the variables corresponds to the named instance
>>         variables.  Fail if the index is not an Integer or is not the index of a
>>         fixed variable.  Answer the value stored as the result. Using this
>>         message violates the  principle that each object has sovereign control
>>         over the storing of values into its instance variables. Essential for the
>>         debugger. See Object documentation whatIsAPrimitive."
>>
>>        <primitive: 74>
>>        "Access beyond fixed fields"
>>        ^self object: anObject basicAt: anIndex - (self objectClass:
>> anObject) instSize put: aValue
>>
>> ContextPart methods for instruction decoding
>> pushReceiverVariable: offset
>>        "Simulate the action of bytecode that pushes the contents of the receiver's
>>        instance variable whose index is the argument, index, on the top of the stack."
>>
>>        self push: (self object: self receiver instVarAt: offset + 1)
>>
>> popIntoReceiverVariable: offset
>>        "Simulate the action of bytecode that removes the top of the stack and
>>        stores it into an instance variable of my receiver."
>>
>>        self object: self receiver instVarAt: offset + 1 put: self pop
>>
>> storeIntoReceiverVariable: offset
>>        "Simulate the action of bytecode that stores the top of the stack into an
>>        instance variable of my receiver."
>>
>>        self object: self receiver instVarAt: offset + 1 put: self top
>>
>> The attached change set for the image level code is also conflated
>> with changes that allow the debugger to set the primitive error code
>> correctly.
>>
>>
>> The VM also needs to implement the primitives.  If the order of the
>> arguments are the same as those of the corresponding non-reflective
>> primitive (e.g. aContext object: theReceiver instVarAt: index put:
>> value has the same order as theReceiver instVarAt: index put: value)
>> and the primitive pops back the stack using self pop: argumentCount +
>> 1, one can use the same VM primitive implementations as the
>> non-reflective ones and so avoid needing extra primitives.
>>
>> However, not all primitives are correctly implemented; e.g. at: and
>> at:put: are, but size is not.  So before we can use this there is some
>> work to do in the standard VMs.  I'm attaching here the implementation
>> in the Stack VM which will require some back porting to the standard
>> VM.  None of these changes has performance implications because the
>> special selector impelmentations of at: at:put: size and #== are not
>> affected.
>>
>> With the above changes one can safely step through code that uses
>> proxies that do not inherit from Object, or even ProtoObject.  I still
>> need to implement a PrimitiveObjectInspector, or use the mirror
>> primitives in implementing the Inspector.  However, there is one more
>> important thing needed in the debugger which these changes do not
>> address and that is the value of Processor activeProcess within  the
>> debugger.  e.g. "print it" the following:
>>
>> | thisProcessOutsideTheDebugger thisProcessInsideTheDebugger |
>> thisProcessOutsideTheDebugger := Processor activeProcess.
>> self halt.
>> thisProcessInsideTheDebugger := Processor activeProcess.
>> 'Send to here (Into) then proceed'.
>> thisProcessOutsideTheDebugger == thisProcessInsideTheDebugger
>>
>> This will potentially break debugging of servers that maintain process
>> pools.  Andreas has proposed a very simple fix for this.  Add an
>> instance variable to Process called, e.g. effectiveProcess, which is
>> nil in normal processes.  When the debugger runs it sets
>> effectiveProcess to that of the process which it is debugging and
>> Processor activeProcess is implemented as something like
>>
>> ProcessorScheduler methods for accessing
>> activeProcess
>>    ^activeProcess effectiveProcess ifNil: [activeProcess]
>>
>> I'll try and get round to this soon.
>
> That appeared to be very easy, because the debugger is well-factored,
> deferring to its interruptedProcess for all execution.  care to bang
> on the attached?  The definition of process is probably wrong for your
> image so integrate that carefully.
>
>
>>
>>
>> I'm posting this rather than integrating because a) the VMs need to
>> get updated before we can use the image level code and, b) the VM
>> folks need code to test their VMs with.  I'm happy to integrate the
>> image-level changes once the VMs have been upgraded.
>>
>> best
>> Eliot
>>
>>>
>>> >
>>> > - Bert -
>>> >
>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko AKA sig.
>>>
>>
>



effectiveProcess.st (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Jecel Assumpcao Jr
In reply to this post by Eliot Miranda-2
I would just like to mention that Self (and it is likely that Newspeak
too, but I haven't looked) has mirror *objects* and not mirror
*primitives*. Yes, these objects actually use primitives to get their
work done but these primitives don't work for any objects other than
mirrors (and if Self didn't have a global namespace for primitives, this
check wouldn't even be necessary since non mirror objects wouldn't even
have a way to try to invoke these primitives).

The mirror objects operate on only one object that is stored as an
"instance variable" when the mirror was created, so you can't pass
random objects as parameters. To have a secure system you would only
have to control the code that allows new mirrors to be created.
Unfortunately, Self didn't do that but instead allows anybody to create
a mirror on anybody else. It wouldn't be very hard to do, however. Of
course, as has already been pointed out this wouldn't get you much in
terms of security if you keep all the current holes that Squeak has.

One possible objection to mirror objects is that you might need to
create them exactly in situations where creating new objects might cause
problems (low memory or certain kinds of bugs).

http://bracha.org/mirrors.pdf has good background information for
anybody having problems keeping up with this thread.

-- Jecel


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Igor Stasenko
In reply to this post by Eliot Miranda-2
2009/9/7 Jecel Assumpcao Jr <[hidden email]>:
> I would just like to mention that Self (and it is likely that Newspeak
> too, but I haven't looked) has mirror *objects* and not mirror
> *primitives*. Yes, these objects actually use primitives to get their
> work done but these primitives don't work for any objects other than
> mirrors (and if Self didn't have a global namespace for primitives, this
> check wouldn't even be necessary since non mirror objects wouldn't even
> have a way to try to invoke these primitives).
>

is this means that mirror primitive implemented to look at some slot
of the receiver
object instead of taking a message argument to reflect the properties
of object to be mirrored?
If so, then it is better, because it makes a bit harder to abuse the prims.

> The mirror objects operate on only one object that is stored as an
> "instance variable" when the mirror was created, so you can't pass
> random objects as parameters. To have a secure system you would only
> have to control the code that allows new mirrors to be created.
> Unfortunately, Self didn't do that but instead allows anybody to create
> a mirror on anybody else. It wouldn't be very hard to do, however. Of
> course, as has already been pointed out this wouldn't get you much in
> terms of security if you keep all the current holes that Squeak has.
>

If we will go at some point to make a secure system, then we should
care at least to not
add a new security gaps and holes in addition to what we already
having - means less work
for people who would want to make a secure system (like Mike van der Gulik)

> One possible objection to mirror objects is that you might need to
> create them exactly in situations where creating new objects might cause
> problems (low memory or certain kinds of bugs).
>
> http://bracha.org/mirrors.pdf has good background information for
> anybody having problems keeping up with this thread.
>
> -- Jecel
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Eliot Miranda-2
In reply to this post by Eliot Miranda-2


Eliot (phone)

On 7 Sep 2009, at 14:35, "Jecel Assumpcao Jr" <[hidden email]>  
wrote:

> I would just like to mention that Self (and it is likely that Newspeak
> too, but I haven't looked) has mirror *objects* and not mirror
> *primitives*. Yes, these objects actually use primitives to get their
> work done but these primitives don't work for any objects other than
> mirrors (and if Self didn't have a global namespace for primitives,  
> this
> check wouldn't even be necessary since non mirror objects wouldn't  
> even
> have a way to try to invoke these primitives).
>
> The mirror objects operate on only one object that is stored as an
> "instance variable" when the mirror was created, so you can't pass
> random objects as parameters. To have a secure system you would only
> have to control the code that allows new mirrors to be created.
> Unfortunately, Self didn't do that but instead allows anybody to  
> create
> a mirror on anybody else. It wouldn't be very hard to do, however. Of
> course, as has already been pointed out this wouldn't get you much in
> terms of security if you keep all the current holes that Squeak has.
>

Ok, that presents a straight-forward e xtension to the primitive  
implementations (forgive typoes; I'm at the park + kids).  If the  
argument count is higher than the base primitive's we insist on the  
receiver being a context who's receiver is the object to be acted  
upon, e.g.

primitiveInstVarAt
     (argumentCount > 2
     and: [(self isIntegerObject: (self stackValue:  argumentCount))
              or: [(self isContext: (self stackValue:  argumentCount))  
not
              or: [(self fetchPointer: ReceiverIndex ofObject: (self  
stackValue:  argumentCount)) ~= (self stackValue: 2)]]]]) ifTrue:
             [^self primitiveFail].

      ....

then the mirror primitives are safe.

Yes?



> One possible objection to mirror objects is that you might need to
> create them exactly in situations where creating new objects might  
> cause
> problems (low memory or certain kinds of bugs).
>
> http://bracha.org/mirrors.pdf has good background information for
> anybody having problems keeping up with this thread.
>
> -- Jecel
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Igor Stasenko
In reply to this post by Igor Stasenko
Thinking a bit about mirrors , i found that they could be useful for
debugging/inspecting purposes without actually exposing the
referenced object contents to sender i.e. instead of:

(objectOrMirroredObject instVarAt: i) printOn: aStream

provide it in a form:

objectOrMirroredObject printInstVarAt: i on: aStream


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Igor Stasenko
In reply to this post by Eliot Miranda-2
2009/9/7 Eliot Miranda <[hidden email]>:

>
>
> Eliot (phone)
>
> On 7 Sep 2009, at 14:35, "Jecel Assumpcao Jr" <[hidden email]> wrote:
>
>> I would just like to mention that Self (and it is likely that Newspeak
>> too, but I haven't looked) has mirror *objects* and not mirror
>> *primitives*. Yes, these objects actually use primitives to get their
>> work done but these primitives don't work for any objects other than
>> mirrors (and if Self didn't have a global namespace for primitives, this
>> check wouldn't even be necessary since non mirror objects wouldn't even
>> have a way to try to invoke these primitives).
>>
>> The mirror objects operate on only one object that is stored as an
>> "instance variable" when the mirror was created, so you can't pass
>> random objects as parameters. To have a secure system you would only
>> have to control the code that allows new mirrors to be created.
>> Unfortunately, Self didn't do that but instead allows anybody to create
>> a mirror on anybody else. It wouldn't be very hard to do, however. Of
>> course, as has already been pointed out this wouldn't get you much in
>> terms of security if you keep all the current holes that Squeak has.
>>
>
> Ok, that presents a straight-forward e xtension to the primitive
> implementations (forgive typoes; I'm at the park + kids).  If the argument
> count is higher than the base primitive's we insist on the receiver being a
> context who's receiver is the object to be acted upon, e.g.
>
> primitiveInstVarAt
>    (argumentCount > 2
>    and: [(self isIntegerObject: (self stackValue:  argumentCount))
>             or: [(self isContext: (self stackValue:  argumentCount)) not
>             or: [(self fetchPointer: ReceiverIndex ofObject: (self
> stackValue:  argumentCount)) ~= (self stackValue: 2)]]]]) ifTrue:
>            [^self primitiveFail].
>
>     ....
>
> then the mirror primitives are safe.
>
> Yes?
>

sorry, can't follow.. its hard to grok through the slang code, even if
its a smalltalk.
Can you please provide the analogous simplified implementation in
non-slang code which will show the actual intent of safety checks?

>
>
>> One possible objection to mirror objects is that you might need to
>> create them exactly in situations where creating new objects might cause
>> problems (low memory or certain kinds of bugs).
>>
>> http://bracha.org/mirrors.pdf has good background information for
>> anybody having problems keeping up with this thread.
>>
>> -- Jecel
>>
>>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Mirror primitives

Eliot Miranda-2
On Mon, Sep 7, 2009 at 5:36 PM, Igor Stasenko<[hidden email]> wrote:

> 2009/9/7 Eliot Miranda <[hidden email]>:
>>
>>
>> Eliot (phone)
>>
>> On 7 Sep 2009, at 14:35, "Jecel Assumpcao Jr" <[hidden email]> wrote:
>>
>>> I would just like to mention that Self (and it is likely that Newspeak
>>> too, but I haven't looked) has mirror *objects* and not mirror
>>> *primitives*. Yes, these objects actually use primitives to get their
>>> work done but these primitives don't work for any objects other than
>>> mirrors (and if Self didn't have a global namespace for primitives, this
>>> check wouldn't even be necessary since non mirror objects wouldn't even
>>> have a way to try to invoke these primitives).
>>>
>>> The mirror objects operate on only one object that is stored as an
>>> "instance variable" when the mirror was created, so you can't pass
>>> random objects as parameters. To have a secure system you would only
>>> have to control the code that allows new mirrors to be created.
>>> Unfortunately, Self didn't do that but instead allows anybody to create
>>> a mirror on anybody else. It wouldn't be very hard to do, however. Of
>>> course, as has already been pointed out this wouldn't get you much in
>>> terms of security if you keep all the current holes that Squeak has.
>>>
>>
>> Ok, that presents a straight-forward e xtension to the primitive
>> implementations (forgive typoes; I'm at the park + kids).  If the argument
>> count is higher than the base primitive's we insist on the receiver being a
>> context who's receiver is the object to be acted upon, e.g.
>>
>> primitiveInstVarAt
>>    (argumentCount > 2
>>    and: [(self isIntegerObject: (self stackValue:  argumentCount))
>>             or: [(self isContext: (self stackValue:  argumentCount)) not
>>             or: [(self fetchPointer: ReceiverIndex ofObject: (self
>> stackValue:  argumentCount)) ~= (self stackValue: 2)]]]]) ifTrue:
>>            [^self primitiveFail].
>>
>>     ....
>>
>> then the mirror primitives are safe.
>>
>> Yes?
>>
>
> sorry, can't follow.. its hard to grok through the slang code, even if
> its a smalltalk.
> Can you please provide the analogous simplified implementation in
> non-slang code which will show the actual intent of safety checks?

primitiveInstVarAt
      argumentCount > 2 ifTrue:"if so this is a mirror prim"
          [ | receiver objectToFetchInstVarFrom |
          receiver := self stackValue: argumentCount.
          objectToFetchInstVarFrom := self stackValue: 2.
          (receiver isContext not
           or: [receiver receiver ~= objectToFetchInstVarFrom]) ifTrue:
               [^self primitiveFail]].

     ... go fetch the inst var ...


>
>>
>>
>>> One possible objection to mirror objects is that you might need to
>>> create them exactly in situations where creating new objects might cause
>>> problems (low memory or certain kinds of bugs).
>>>
>>> http://bracha.org/mirrors.pdf has good background information for
>>> anybody having problems keeping up with this thread.
>>>
>>> -- Jecel
>>>
>>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>

Reply | Threaded
Open this post in threaded view
|

RE: [squeak-dev] Re: Mirror primitives [Was The better debugger supportby extending an Object protocol]

Terry Raymond-2
In reply to this post by Eliot Miranda-2
Instead of implementing #activeProcess as

activeProcess
    ^activeProcess effectiveProcess ifNil: [activeProcess]

Why not have the effectiveProcess ivar point to the receiver
unless debugging is in process. Then #activeProcess would be

activeProcess
        ^activeProcess effectiveProcess

and effectiveProcess would be

effectiveProcess
        ^effectiveProcess


Terry
 
===========================================================
Terry Raymond
Crafted Smalltalk
80 Lazywood Ln.
Tiverton, RI  02878
(401) 624-4517      [hidden email]
<http://www.craftedsmalltalk.com>
===========================================================


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Mirror primitives [Was The better debugger supportby extending an Object protocol]

Eliot Miranda-2
On Tue, Sep 8, 2009 at 6:20 AM, Terry Raymond<[hidden email]> wrote:

> Instead of implementing #activeProcess as
>
> activeProcess
>    ^activeProcess effectiveProcess ifNil: [activeProcess]
>
> Why not have the effectiveProcess ivar point to the receiver
> unless debugging is in process. Then #activeProcess would be
>
> activeProcess
>        ^activeProcess effectiveProcess
>
> and effectiveProcess would be
>
> effectiveProcess
>        ^effectiveProcess

In the end I put the check in Process>>effectiveProcess.  I don't want
to have to guarantee that effectiveProcess gets assigned on Process
creation.  There isn't an existing Process>>initialize method so I
didn't want to add overhead or tax a ref counting GC etc, etc.  So I
ended up with what you have above except for

effectiveProcess
       ^effectiveProcess ifNil: [self]

>
>
> Terry
>
> ===========================================================
> Terry Raymond
> Crafted Smalltalk
> 80 Lazywood Ln.
> Tiverton, RI  02878
> (401) 624-4517      [hidden email]
> <http://www.craftedsmalltalk.com>
> ===========================================================
>
>
>

12