(I hope you don't mind me posting to n.p.m.xpcom, as this is a good question that we should explore...)
Jon Smirl wrote:
do you have specific examples of this? I guess what we've always tried to do is keep the communication between components at the interface level, so this shouldn't be an issue.There is a real danger of invisible binary linkages between components because of the use of classes in public h files that provide inline functions accessing member data. For example component A makes a class in it's header that includes an inline function that references member variables. Component B uses this function. Now we need to do a security update to Component A that changes the binary layout of the public class. You won't be able to just ship a new component A, you will have to ship every component that includes Component A's h file (either that or track down everyone who used the inline function). There is no simple way to find these linkages other than a mass inspection of the code, because of inlining they don't show as exported symbols.
For example
Let's say I have component A with an internal class nsA, implementing an interface nsIA. Now let's say there's an inline function that component A exports via a header file,
NS_DoSomeWorkWithA(nsIA* foo) {
foo->CallSomeMethod();
}
Now, component B uses this function... but it turns out that nsA::CallSomeMethod() is horribly insecure for some reason. We fix nsA::CallSomeMethod() and ship a new component A, but do not change the interface definition nsIA. component B will continue to work correctly because we're calling across interface boundaries. even if the structure of nsA (the concrete class) changes, the vtables will remain the same.
Now in the case that NS_DoSomeWorkWithA itself is the dangerous function, I think we have no choice but to re-ship component B as well. I think this is totally reasonable though.. its the price we pay for the convenience of inlining functions, and I think the public vs. private nature of them is just as well. I guess my expectation is that inlined functions should be simple and simple means less risk [of security issues..]
This is actually something we've discussed in the embedded context before - but what we basically wanted was a very small set of public interfaces.. i.e. literally 95% of the current interfaces should remain private...What do you think about changing the REQUIRES support to split h files into dist/include/public/* and dist/include/private/*? The public directory would only contain h files that are generated from IDL files. Private would contain everything else. The REQUIRES support would include all the public directories and only the private directory for that module.
the idea is that we ship an SDK out of the dist/include/public directory... we'd still want dist/include/public/<modulename> of course...
Alec
