Guard against calling malloc(0) when create ByteBuffer. (#7948)
Motivation: We did not guard against the case of calling malloc(0) when creating a ByteBuffer without a Cleaner. The problem is that malloc(0) can have different behaviour, it either return a null-pointer or a valid pointer that you can pass to free. The real problem arise if Unsafe.allocateMemory(0) returns 0 and we use it as the memoryAddress of the ByteBuffer. The problem here is that native libraries test for 0 and handle it as a null-ptr. This is for example true in SSL.bioSetByteBuffer(...) which would throw a NPE when 0 is used as memoryAddress and so produced errors during SSL usage. Modifications: - Always allocate 1 byte as minimum (even if we ask for an empty buffer). - Add unit test. Result: No more errors possible because of malloc(0).
This commit is contained in:
parent
546ddd2c28
commit
c3d29f7b9e
@ -427,7 +427,10 @@ final class PlatformDependent0 {
|
||||
}
|
||||
|
||||
static ByteBuffer allocateDirectNoCleaner(int capacity) {
|
||||
return newDirectBuffer(UNSAFE.allocateMemory(capacity), capacity);
|
||||
// Calling malloc with capacity of 0 may return a null ptr or a memory address that can be used.
|
||||
// Just use 1 to make it safe to use in all cases:
|
||||
// See: http://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html
|
||||
return newDirectBuffer(UNSAFE.allocateMemory(Math.max(1, capacity)), capacity);
|
||||
}
|
||||
|
||||
static boolean hasAllocateArrayMethod() {
|
||||
|
@ -17,14 +17,13 @@ package io.netty.util.internal;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Random;
|
||||
|
||||
import static io.netty.util.internal.PlatformDependent.hashCodeAscii;
|
||||
import static io.netty.util.internal.PlatformDependent.hashCodeAsciiSafe;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
public class PlatformDependentTest {
|
||||
private static final Random r = new Random();
|
||||
@ -146,4 +145,13 @@ public class PlatformDependentTest {
|
||||
hashCodeAscii(string));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllocateWithCapacity0() {
|
||||
assumeTrue(PlatformDependent.hasDirectBufferNoCleanerConstructor());
|
||||
ByteBuffer buffer = PlatformDependent.allocateDirectNoCleaner(0);
|
||||
assertNotEquals(0, PlatformDependent.directBufferAddress(buffer));
|
||||
assertEquals(0, buffer.capacity());
|
||||
PlatformDependent.freeDirectNoCleaner(buffer);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user