Slashdot Mirror


Gosling Claims Huge Security Hole in .NET

renai42 writes "Java creator James Gosling this week called Microsoft's decision to support C and C++ in the common language runtime in .NET one of the 'biggest and most offensive mistakes that they could have made.' Gosling further commented that by including the two languages into Microsoft's software development platform, the company 'has left open a security hole large enough to drive many, many large trucks through.'" Note that this isn't a particular vulnerability, just a system of typing that makes it easy to introduce vulnerabilities, which last time I checked, all C programmers deal with.

5 of 687 comments (clear)

  1. It's called unsafe code for a reason by jerometremblay · · Score: 4, Informative

    Unsafe code is not subject to security checks of the .NET virtual machine. To execute unsafe code, you have to specifically grant those rights to the executing program. It is not something automatic.

    Applications that require safety (for example running plugins downloaded from the net) simply don't allow those assemblies to be loaded.

    Where is the problem again?

  2. Re:Java is a type-safe language at the VM level... by patniemeyer · · Score: 4, Informative

    Yes, actually, it does. Have you checked it recently? The only overhead that natively compiled Java code would have over comparable C++ is that it always does array bounds checking. Other than that you just have to ask yourself, what kind of optimization can a static compiler (C/C++) do that a dynamic, profiling runtime compiler (Java) can't do?

    Garbage collection in Java has been faster than free/malloc in C for years. This is in large part due to the fact that the runtime can recognize very short lived objects and put them on a special part of the heap.

    It's not necessary to use unsafe languages to get performance any more.

    Pat Niemeyer

  3. Re:JNI by patniemeyer · · Score: 4, Informative

    But JNI is not Java... It's an API. For that matter you might consider sockets and network connections to make Java unsafe because they could invoke unsafe applications.

    It is completely fair to point out that .NET allows you to choose safe vs. unsafe code... but it is a little different from the Java scenario in that this is unsafe code that is run through the VM. It's just an odd choice to make.

    Pat Niemeyer
    Author of Learning Java, O'Reilly & Associates

  4. Re:Java is a type-safe language at the VM level... by hobuddy · · Score: 4, Informative

    You're quite right that Java's speed is excellent these days (for non-GUI code, at least). I've spent a lot of time recently working with a large system that was first implemented in Java (by highly skilled developers) and then ported to C++ (by greenhorns). The C++ port is only 50-100% faster, which isn't worth the price in developer time that's been wasted on memory leaks and other forms of memory corruption that were never a factor in Java. Besides that, supporting multiple platforms with the C++ version is the #definition of pain.

    However, the C++ version uses only about 1/4 or 1/5 as much memory as the Java version, and starts up far more quickly. If a *desktop* application needs to be deployed on older machines, or if the application is so memory-intensive it taxes the limits of today's server hardware, Java still falls flat.

    --
    Erlang.org: wow
  5. malloc+free: fast, simple, and can be even faster by nothings · · Score: 4, Informative
    Malloc and free are simple algorithms, and whoever told you otherwise was wrong.

    I don't know where you got your understanding of malloc, and especially free, but it's severely out of date. Knuth published about "Boundary Tags" no later than 1973 (citeseer is down, so no link). Saying that a coalesce operation "can be arbirarily slow" is just FUD. A boundary tag makes free() a fast O(1) operation: check the previous block in memory to see if it's free and if so join, a fast O(1) operation; check the next block in memory to see if it's free and if so coalesce; add free block to free-list, done. Yes, it's not zero work like a GC implementation sort-of is, but "arbitrarily slow"? It's basically at least as fast as malloc().

    Allocation requests can hit disk, sure, but so can GC allocations even if they're just bumping a pointer: it all depends on the working set size. GC compaction can reduce fragmentation to reduce working set size, but that is only a big win if there's a lot of fragmentation, and most apps using a good malloc() don't exhibit that much. (It is also possible for a GC to rearrange memory so more in-working-set data is on pages together, reducing the working set page count without changing the total memory used. I don't know of any in-use implementations of this, since you need hardware support to know what objects are more-in-use; generally this is only available at the page level, where it's no help. I think maybe an early microde-based Smalltalk implementation might have done this.)

    If your malloc has to walk giant free lists to find an open block, then sure, that can be slow. That's why people use trees of free lists based on size and such to make it more O(log N), and O(1) for small allocations. (On large allocations, actually using the memory amortizes the cost.) Read about dlmalloc, for example.

    Furthermore, let's not misrepresent GC. Stop-and-collect GCs have obvious extra costs beyond the free-of-charge free (or lack of need for one). Incremental GCs that don't pause are usually slower overall and only preferred for interactive programs. For example, incremental GCs usually require "write barriers" or "read barriers" which require several extra instruction on every fetch from memory or every write of a pointer variable in memory. This can add up across the entire program. Incremental GCs also tend to be conservative, and only end up collecting things that, say, were garbage at the start of the most recent collection round, and generational collectors allow garbage to collect in later generations for some time, so they don't actually necessarily have a smaller working set than a non-leaky malloc()/free() program.

    Another big win in non-GC systems is that you can use pointers that don't come off the heap. That way you can avoid allocation and deallocation and GC entirely. (You can actually do some of this in a GC system too if it's a 'conservative' GC that copes with pointers into the middle of blocks. Those pretty much only get used for adding GC to C and C++, though.) Here are some common ways this happens:

    • statically allocated arrays
    • small arrays and strcts on the stack
    • structs that are components of other structs, or arrays at the end of structs
    • use of special allocators:
      • slab allocators (it's even possible to embed this entirely inside the default allocator for all small allocations)
      • pool allocators (allocate a large block of memory, suballocate from it, deallocate all at once)
      • "stack" allocators (allocate a large block of memory, suballocate from one end, only allow freeing from the same end, so allocation is a adding to a pointer and deallocation is reseting that pointer)

    Of course, doing all these things requires that you balance your different types of malloc()s with the correct, matching type of free(). In practice, GC proponents overestimate the diffi