Skip to content

Commit 4c387d9

Browse files
committed
Fix include. Add unit tests. Impl same checks for windoof too.
1 parent d5966b3 commit 4c387d9

3 files changed

Lines changed: 57 additions & 7 deletions

File tree

src/main/cpp/_nix_based/jssc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <limits.h>
2727
#include <stdio.h>
2828
#include <fcntl.h>
29+
#include <new> // std::bad_alloc
2930
#include <string.h>
3031
#include <unistd.h>
3132
#include <string.h>

src/main/cpp/windows/jssc.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,17 +276,33 @@ JNIEXPORT jbyteArray JNICALL Java_jssc_SerialNativeInterface_readBytes
276276
HANDLE hComm = (HANDLE)portHandle;
277277
DWORD lpNumberOfBytesTransferred;
278278
DWORD lpNumberOfBytesRead;
279+
jbyteArray returnArray = NULL;
279280
jbyte *lpBuffer = NULL;
281+
OVERLAPPED *overlapped = NULL;
280282

281-
jbyteArray returnArray = env->NewByteArray(byteCount);
283+
if( byteCount < 0 ){
284+
/* Negative byteCount makes no sense -> Report to caller by exception. */
285+
char exMsg[48]; exMsg[0] = '\0';
286+
snprintf(exMsg, sizeof exMsg, "byteCount %d", byteCount);
287+
jclass exClz = env->FindClass("java/lang/IllegalArgumentException");
288+
if( exClz != NULL ) env->ThrowNew(exClz, exMsg);
289+
goto Finally;
290+
}
291+
292+
returnArray = env->NewByteArray(byteCount);
293+
if( returnArray == NULL ) goto Finally;
282294

283295
lpBuffer = (jbyte *)malloc(byteCount * sizeof(jbyte));
284296
if(lpBuffer == NULL){
285-
// return an empty array
286-
return returnArray;
297+
/* Whops. Not enough memory. Let caller know through exception. */
298+
char exMsg[32]; exMsg[0] = '\0';
299+
snprintf(exMsg, sizeof exMsg, "malloc(%d)", byteCount);
300+
jclass exClz = env->FindClass("java/lang/OutOfMemoryError");
301+
if( exClz != NULL ) env->ThrowNew(exClz, exMsg);
302+
goto Finally;
287303
}
288304

289-
OVERLAPPED *overlapped = new OVERLAPPED();
305+
overlapped = new OVERLAPPED();
290306
overlapped->hEvent = CreateEventA(NULL, true, false, NULL);
291307
if(ReadFile(hComm, lpBuffer, (DWORD)byteCount, &lpNumberOfBytesRead, overlapped)){
292308
env->SetByteArrayRegion(returnArray, 0, byteCount, lpBuffer);
@@ -302,9 +318,12 @@ JNIEXPORT jbyteArray JNICALL Java_jssc_SerialNativeInterface_readBytes
302318
jclass exClz = env->FindClass("java/lang/IllegalArgumentException");
303319
if( exClz != NULL ) env->ThrowNew(exClz, "EBADF");
304320
}
305-
CloseHandle(overlapped->hEvent);
306-
delete overlapped;
307-
free(lpBuffer);
321+
Finally:
322+
if( overlapped != NULL ){
323+
CloseHandle(overlapped->hEvent);
324+
delete overlapped;
325+
}
326+
if( lpBuffer != NULL ) free(lpBuffer);
308327
return returnArray;
309328
}
310329

src/test/java/jssc/SerialNativeInterfaceTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,34 @@ public void throwsNpeIfPassedBufferIsNull() throws Exception {
9494
new SerialNativeInterface().writeBytes(1, null);
9595
}
9696

97+
@Test
98+
public void throwsIaeIfCountNegative() throws Exception {
99+
SerialNativeInterface testTarget = new SerialNativeInterface();
100+
byte[] ret;
101+
try{
102+
ret = testTarget.readBytes(0, -42);
103+
fail("Where's the exception?");
104+
}catch( IllegalArgumentException ex ){
105+
assertTrue(ex.getMessage().contains("-42"));
106+
}
107+
}
108+
109+
@Test
110+
@org.junit.Ignore("This test only makes sense if it is run in a situation"
111+
+" where large memory allocations WILL fail (for example you could use"
112+
+" a virtual machine with low memory available). Because on regular"
113+
+" machines allocating 2GiB of RAM is not a problem at all and so the"
114+
+" test run will just happily wait infinitely for those 2GiB to arrive"
115+
+" at the stdin fd. Feel free to remove this test if you think it"
116+
+" doesn't make sense to have it here.")
117+
public void throwsOOMExIfRequestTooLarge() throws Exception {
118+
SerialNativeInterface testTarget = new SerialNativeInterface();
119+
try{
120+
byte[] ret = testTarget.readBytes(0, Integer.MAX_VALUE);
121+
fail("Where's the exception?");
122+
}catch( OutOfMemoryError ex ){
123+
assertTrue(ex.getMessage().contains(String.valueOf(Integer.MAX_VALUE)));
124+
}
125+
}
126+
97127
}

0 commit comments

Comments
 (0)