Skip to content

Commit bc9f440

Browse files
committed
Remove the VLAs in the JNI code so we don't get stack overflows when operating on large blobs
Also recompiled the libsodium AAR with the latest NDK (v29.0.14206865).
1 parent 41643a6 commit bc9f440

File tree

7 files changed

+47
-21
lines changed

7 files changed

+47
-21
lines changed

.idea/deploymentTargetSelector.xml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/CMakeLists.txt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ project(georgenative)
88

99
find_package(sodium REQUIRED CONFIG)
1010

11-
# use a 16 KB page size
12-
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
13-
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
14-
1511
# Creates and names a library, sets it as either STATIC
1612
# or SHARED, and provides the relative paths to its source code.
1713
# You can define multiple libraries, and CMake builds it for you.
@@ -29,5 +25,5 @@ add_library( # Sets the name of the library.
2925
src/main/cpp/sodium.c)
3026

3127
target_include_directories(native-lib PRIVATE)
32-
target_link_libraries(native-lib android sodium::sodium log)
28+
target_link_libraries(native-lib android sodium::sodium-minimal log)
3329

app/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
compileSdk = 36
1313
minSdkVersion 29
1414
targetSdkVersion 36
15-
versionCode 61
16-
versionName "0.61"
15+
versionCode 65
16+
versionName "0.65"
1717
multiDexEnabled = true
1818
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1919
resourceConfigurations += ['en', 'tr', 'ru']
@@ -78,7 +78,7 @@ android {
7878
sourceCompatibility JavaVersion.VERSION_11
7979
targetCompatibility JavaVersion.VERSION_11
8080
}
81-
ndkVersion = '29.0.14033849'
81+
ndkVersion = '29.0.14206865'
8282
namespace = 'xyz.zood.george'
8383
packagingOptions {
8484
jniLibs {

app/libs/libsodium-1.0.20.0.aar

933 Bytes
Binary file not shown.

app/src/main/cpp/sodium.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ JNIEXPORT jobject JNICALL Java_io_pijun_george_Sodium_symmetricKeyEncrypt(
9696
JNIEnv *env, jclass cls, jbyteArray msg, jbyteArray key) {
9797
unsigned long long msgLen = (unsigned long long)(*env)->GetArrayLength(env, msg);
9898
unsigned long long cipherTextLen = msgLen + crypto_secretbox_MACBYTES;
99-
unsigned char cipherText[cipherTextLen];
99+
unsigned char* cipherText = malloc(cipherTextLen);
100+
if (cipherText == NULL) {
101+
__android_log_print(ANDROID_LOG_ERROR, "ZoodLoc", "symmetricKeyEncrypt: failed to allocate cipherText");
102+
return NULL;
103+
}
100104
unsigned char* msgUChar = ucharArray(env, msg);
101105
unsigned char nonceUChar[crypto_secretbox_NONCEBYTES];
102106
unsigned char* keyUChar = ucharArray(env, key);
@@ -109,6 +113,7 @@ JNIEXPORT jobject JNICALL Java_io_pijun_george_Sodium_symmetricKeyEncrypt(
109113
free(msgUChar);
110114
free(keyUChar);
111115
if (result != 0) {
116+
free(cipherText);
112117
return NULL;
113118
}
114119

@@ -124,6 +129,7 @@ JNIEXPORT jobject JNICALL Java_io_pijun_george_Sodium_symmetricKeyEncrypt(
124129
jbyteArray nonceByteArray = byteArray(env, (unsigned char*)nonceUChar, crypto_secretbox_NONCEBYTES);
125130
(*env)->SetObjectField(env, skem, nonceFieldId, nonceByteArray);
126131

132+
free(cipherText);
127133
return skem;
128134
}
129135

@@ -136,7 +142,11 @@ JNIEXPORT jbyteArray JNICALL Java_io_pijun_george_Sodium_symmetricKeyDecrypt(
136142
return NULL;
137143
}
138144

139-
unsigned char msgUChar[msgLen];
145+
unsigned char* msgUChar = malloc(msgLen);
146+
if (msgUChar == NULL) {
147+
__android_log_print(ANDROID_LOG_ERROR, "ZoodLoc", "symmetricKeyDecrypt: failed to allocate msgUChar");
148+
return NULL;
149+
}
140150
unsigned char* cipherTextUChar = ucharArray(env, cipherText);
141151
unsigned char* nonceUChar = ucharArray(env, nonce);
142152
unsigned char* keyUChar = ucharArray(env, key);
@@ -150,10 +160,12 @@ JNIEXPORT jbyteArray JNICALL Java_io_pijun_george_Sodium_symmetricKeyDecrypt(
150160
free(keyUChar);
151161
if (result != 0) {
152162
__android_log_print(ANDROID_LOG_INFO, "ZoodLoc", "symmetricKeyDecrypt: non-zero result (%d)", result);
163+
free(msgUChar);
153164
return NULL;
154165
}
155166

156167
jbyteArray msg = byteArray(env, msgUChar, msgLen);
168+
free(msgUChar);
157169
return msg;
158170
}
159171

@@ -162,7 +174,11 @@ JNIEXPORT jobject JNICALL Java_io_pijun_george_Sodium_publicKeyEncrypt(
162174
JNIEnv *env, jclass cls, jbyteArray msg, jbyteArray rcvrPubKey, jbyteArray sndrSecKey) {
163175
int msgLen = (*env)->GetArrayLength(env, msg);
164176
int cipherTextLen = crypto_box_MACBYTES + msgLen;
165-
unsigned char cipherText[cipherTextLen];
177+
unsigned char* cipherText = malloc(cipherTextLen);
178+
if (cipherText == NULL) {
179+
__android_log_print(ANDROID_LOG_ERROR, "ZoodLoc", "publicKeyEncrypt: failed to allocate cipherText");
180+
return NULL;
181+
}
166182
unsigned char nonce[crypto_box_NONCEBYTES];
167183
randombytes_buf(nonce, sizeof nonce);
168184
unsigned char* msgUChar = ucharArray(env, msg);
@@ -179,6 +195,7 @@ JNIEXPORT jobject JNICALL Java_io_pijun_george_Sodium_publicKeyEncrypt(
179195
free(sndrKeyUChar);
180196
if (result != 0) {
181197
__android_log_print(ANDROID_LOG_INFO, "ZoodLoc", "publicKeyEncrypt: non-zero result (%d)", result);
198+
free(cipherText);
182199
return NULL;
183200
}
184201

@@ -194,6 +211,7 @@ JNIEXPORT jobject JNICALL Java_io_pijun_george_Sodium_publicKeyEncrypt(
194211
jbyteArray nonceByteArray = byteArray(env, nonce, sizeof nonce);
195212
(*env)->SetObjectField(env, skem, nonceFieldId, nonceByteArray);
196213

214+
free(cipherText);
197215
return skem;
198216
}
199217

@@ -206,7 +224,11 @@ JNIEXPORT jbyteArray JNICALL Java_io_pijun_george_Sodium_publicKeyDecrypt(
206224
__android_log_print(ANDROID_LOG_INFO, "ZoodLoc", "publicKeyDecrypt: message is too short");
207225
return NULL;
208226
}
209-
unsigned char msg[msgLen];
227+
unsigned char* msg = malloc(msgLen);
228+
if (msg == NULL) {
229+
__android_log_print(ANDROID_LOG_ERROR, "ZoodLoc", "publicKeyDecrypt: failed to allocate msg");
230+
return NULL;
231+
}
210232
unsigned char* cipherTextUChar = ucharArray(env, cipherText);
211233
unsigned char* nonceUChar = ucharArray(env, nonce);
212234
unsigned char* pubKeyUChar = ucharArray(env, senderPubKey);
@@ -223,10 +245,13 @@ JNIEXPORT jbyteArray JNICALL Java_io_pijun_george_Sodium_publicKeyDecrypt(
223245
free(secKeyUChar);
224246
if (result != 0) {
225247
__android_log_print(ANDROID_LOG_INFO, "ZoodLoc", "publicKeyDecrypt: non-zero result (%d)", result);
248+
free(msg);
226249
return NULL;
227250
}
228251

229-
return byteArray(env, msg, msgLen);
252+
jbyteArray result_array = byteArray(env, msg, msgLen);
253+
free(msg);
254+
return result_array;
230255
}
231256

232257
#pragma clang diagnostic pop

app/src/main/java/io/pijun/george/MessageProcessor.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import java.util.Arrays;
1616

1717
import io.pijun.george.api.DeviceInfo;
18-
import io.pijun.george.api.LimitedUserInfo;
18+
import io.pijun.george.api.LimitedUserInfoUnchecked;
1919
import io.pijun.george.api.Message;
2020
import io.pijun.george.api.MessageConverter;
2121
import io.pijun.george.api.OscarAPI;
@@ -109,7 +109,7 @@ public static Result decryptAndProcess(@NonNull Context context, @NonNull byte[]
109109
// we need to retrieve it from the server
110110
OscarAPI api = OscarClient.newInstance(token);
111111
try {
112-
Response<LimitedUserInfo> response = api.getUser(Hex.toHexString(senderId)).execute();
112+
Response<LimitedUserInfoUnchecked> response = api.getUser(Hex.toHexString(senderId)).execute();
113113
if (!response.isSuccessful()) {
114114
OscarError apiErr = OscarError.fromResponse(response);
115115
if (apiErr == null) {
@@ -126,11 +126,16 @@ public static Result decryptAndProcess(@NonNull Context context, @NonNull byte[]
126126
return Result.ErrorUnknown;
127127
}
128128
}
129-
LimitedUserInfo lui = response.body();
130-
if (lui == null) {
129+
LimitedUserInfoUnchecked luiu = response.body();
130+
if (luiu == null) {
131131
L.w("Unable to decode user " + Hex.toHexString(senderId) + " from response");
132132
return Result.ErrorUnknown;
133133
}
134+
var lui = luiu.toLimitedUserInfo();
135+
if (lui == null) {
136+
L.w("Decoded user " + Hex.toHexString(senderId) + " had a null username or public key");
137+
return Result.ErrorUnknown;
138+
}
134139
// now that we've encountered a new user, add them to the database (because of TOFU)
135140
user = db.addUser(senderId, lui.username, lui.publicKey);
136141
L.i(" added user: " + user);

app/src/main/java/io/pijun/george/api/OscarAPI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public interface OscarAPI {
5454
Call<ServerPublicKeyResponse> getServerPublicKey();
5555

5656
@GET("users/{id}")
57-
Call<LimitedUserInfo> getUser(@Path("id") String hexId);
57+
Call<LimitedUserInfoUnchecked> getUser(@Path("id") String hexId);
5858

5959
@GET("drop-boxes/{boxId}")
6060
Call<EncryptedData> pickUpPackage(@Path("boxId") String hexId);

0 commit comments

Comments
 (0)