0

I often encounter situations where I pass instances as parameters to functions. It occurred to me that it is equally possible to forward the parameters of the object instead, and initialize within the method.

Example:

class MyCanvas extends JComponent {

    private static final long serialVersionUID = 1L;

    private static ArrayList<String>    textData;
    private static ArrayList<Rectangle> rectData;

    @Override

    public void paintComponent(Graphics g) {

        if(g instanceof Graphics2D){

            //Draw the rectangles and text
        }
    }

    public void addText(int x, int y, String text){
        textData.add(text);
    }

    //Do this:
    public void addRect(Rectangle rect){
        rectData.add(rect);
    }

    //Or do this?
    public void addRect(int x, int y, int z,  int q){
        rectData.add(new Rectangle(x, y, z, q);
    }

}

Passing four integers, in this case, reduces the variability. Theoretically speaking, the error surface area should be reduced along with the potential for vulnerabilities.

How does the JVM handle these two examples differently?

Is one truly less error/vulnerability prone?

Will one be more efficient than the other in terms of performance?

Note: This is not a question about design preference. There are multiple ways wrap or bind parameters in such a way that either example would be flexible and efficient. All I want to know is what the difference is on the byte code level, and whether or not one is distinctly more efficient/secure at the bytecode level.

bigcodeszzer
  • 916
  • 1
  • 8
  • 27
  • "Or forward the parameters and initialize it in the method?" If you simply use a bunch of parameters to create a `Frobnitz`, pass a `Frobnitz` instance instead. This reduces the right coupling to a particular implementation of `Frobnitz`, e.g. making it easier to test by allowing you to pass in a `MockFrobnitz`. – Andy Turner Jul 13 '16 at 15:21
  • Also, if alteration of object after it was passed to function is what you are worried about, you can use cloning inside the method. – Coderino Javarino Jul 13 '16 at 15:22
  • Or wrap the instance in a [facade](https://en.wikipedia.org/wiki/Facade_pattern), so you only expose the methods you want others to use. – Andy Turner Jul 13 '16 at 15:23
  • 2
    What's the threat here? Is `MyCanvas` written by a terrorist? – erickson Jul 13 '16 at 15:55
  • @erickson Not funny. And the point here is about design habits, they reduce attack surface area. I, personally, don't want to be responsible for writing poorly structured code of any kind. – bigcodeszzer Jul 13 '16 at 16:35
  • 2
    It's not meant to be funny. You didn't define the threat you are trying to mitigate, so asking for the most secure solution makes no sense. By casting things in an absurd extreme, my question was a prompt for you to clarify your goal. – erickson Jul 13 '16 at 16:46
  • Look at the two answers so far. I assumed you want to prevent corruption of objects shared as call parameters. [Bruce](http://stackoverflow.com/a/38356424/3474) is talking about privacy protection for those parameters, which never occurred to me. What are you looking for? – erickson Jul 13 '16 at 16:56
  • Question majorly edited. – bigcodeszzer Jul 13 '16 at 17:07
  • You still don't say what you mean by "secure." And do you want to be memory-efficient or time-efficient? It's a tradeoff. – erickson Jul 13 '16 at 17:14
  • @erickson clarified both terms in edit – bigcodeszzer Jul 13 '16 at 17:25

3 Answers3

1

Be alert to the distinction between architectural security and linguistic security. Most computer science professors are not, in fact, aware thereof.

If you want to "securely" pass an object, you could prompt at the keyboard for an encryption key; collect the key; encrypt the object; and pass it. The receiving function could then re-prompt and reverse the encryption! It all depends what you're trying to accomplish.

The lifetime of the object is the biggest concern. Once it has been passed, the parameter value sits on the stack; if we postulate an observer that can view memory locations belonging to the JVM, then we're hosed. So, once the value has been retrieved, overwrite it in situ with garbage. We call this an "object reuse" consideration, although we typically bear it in mind when freeing objects back to the system: we don't implicitly assume some guy sharing our address space and continually peeking here and poking there.

1

From an API design perspective, passing a Rectangle (or a Shape) is better. It supports coding to an interface, not an implementation. In one sense, specifying a corner and dimensions is an implementation; a different implementation would specify opposite corners. By passing a shape, you make your code more adaptable.

The main problem here is due to the mutability of Rectangle. There are efficiency arguments for this, but I wonder if Shape would be mutable if it were designed today. For many applications, immutable data types provide many benefits, and safer sharing of data is one of them.

Since you are implementing MyCanvas, you can satisfy yourself that the Rectangle instance is not modified, and is therefore "secure." However, if someone else is writing the caller, and MyCanvas is a black box they can't fully trust, there are two things that can help.

First, you can document the MyCanvas methods that accept a shape, specifying that the shapes are not modified. In Java, this specification should be placed in Javadoc comments on methods and classes. This is a common practice; unless you are writing a plugin system that might execute agents that are written by untrustworthy authors, programmers typically rely on this commitment, or contract, in an API.

Second, if the caller doesn't have that assurance, they can copy "their" Rectangle instance to a temporary copy, and pass you the copy. Because they never read the state of the Rectangle after the method returns, it doesn't matter what you do to it. Because Rectangle is mutable, this can be done fairly efficiently.


From a byte code perspective, passing the Rectangle is faster. An separate instruction is executed for each parameter that is passed. More parameters, more instructions. Also, passing the Rectangle allows the caller's instance to be re-used, while passing primitive elements requires allocation of a new Rectangle that might be unnecessary.

I don't know what you talking about when you say, "Passing four integers, in this case, reduces the variability. Theoretically speaking, the error surface area should be reduced along with the potential for vulnerabilities."

I do know that in the real, practical world, methods with multiple arguments of the same type, like four int parameters, are extremely error-prone. Naming them nonsense like q and z makes that problem even worse. Taking advantage of strong typing for parameters makes your program safer by eliminating bugs at compile-time.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • Isn't int[] an instance in java anyway? If function calls do add instructions, it would seem more efficient to cut out as much wrapper code as possible. – bigcodeszzer Jul 13 '16 at 18:26
  • What if the instance is bound to the parameters? – bigcodeszzer Jul 13 '16 at 18:27
  • As far as error surface, in the case of forwarding, if the user is providing the input, they can only pass integers. If the user also has inderect access to the instance constructor, there is more 'surface area' for potential vulnerabilities. At least, that's what they said in school. It's not really a big deal for rectangle() but it's a minimal example. – bigcodeszzer Jul 13 '16 at 18:31
  • @bigcodeszzer Yes, `int[]` is an object instance. You aren't asking about `int[]` though, and I don't see its relevance. If you are suggesting that `int[]` is a good alternative to `Rectangle`, I strongly disagree. It's a design abomination. The only performance it *might* offer is locality of reference, but I would expect the fields of a `Rectangle` to be located similarly, and in any case they aren't sequentially read in a way that would make good use of that locality. I don't understand the question, "What if the instance is bound to the parameters?" What instance? What does "bound" mean? – erickson Jul 13 '16 at 18:33
  • In c++ you can 'bind' parameters to a function/constructor, treating it as a single, immutable data type. – bigcodeszzer Jul 13 '16 at 18:35
  • I think you can do it Java too? – bigcodeszzer Jul 13 '16 at 18:35
  • @bigcodeszzer Nope. You might be thinking of lambdas, but it's not clear how you intend to apply it here. If you have something specific in mind, add a code example to your question (or open a new question, since this one is already unfocused). – erickson Jul 13 '16 at 18:38
1

In the beginning you have 4 ints and in the end a Rectangle is required. It all boils down to whose responsibility it is to validate the input and make the conversion.

While this particular example is very simple, you could make it more interesting by adding:

public void addRect(String rect){
  // e.g. rect = "4 2 3 7"
}  

public void addRect(int[] rect){
  // e.g. rect = [4 2 3 7]
}      

// etc...

in which case it can be argued that the caller should not care how the rectangles are constructed and that is the business of the MyCanvas class

David Soroko
  • 8,521
  • 2
  • 39
  • 51