Skip to content

Commit 6357508

Browse files
authored
Avoid passing invalid utf8 str to JNI. (k2-fsa#3527)
1 parent 9c56e6c commit 6357508

12 files changed

Lines changed: 38 additions & 24 deletions

sherpa-onnx/jni/audio-tagging.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_k2fsa_sherpa_onnx_AudioTagging_compute(
154154
for (size_t i = 0; i < events.size(); ++i) {
155155
const auto &e = events[i];
156156

157-
jstring name = env->NewStringUTF(e.name.c_str());
157+
jstring name = SafeNewStringUTF(env, e.name);
158158
jobject event_obj = env->NewObject(cls, ctor, name, e.index, e.prob);
159159

160160
env->SetObjectArrayElement(obj_arr, i, event_obj);

sherpa-onnx/jni/common.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include <string>
99

10+
#include "sherpa-onnx/csrc/text-utils.h"
11+
1012
#if __ANDROID_API__ >= 9
1113
#include <sstream>
1214

@@ -142,6 +144,18 @@
142144
jobject NewInteger(JNIEnv *env, int32_t value);
143145
jobject NewFloat(JNIEnv *env, float value);
144146

147+
// Wrapper for NewStringUTF that strips invalid UTF-8 byte sequences first.
148+
// This prevents JNI crashes when the ASR model outputs invalid UTF-8
149+
// (e.g., orphaned UTF-16 surrogate halves from the Arabic moonshine model).
150+
inline jstring SafeNewStringUTF(JNIEnv *env, const std::string &s) {
151+
return env->NewStringUTF(sherpa_onnx::RemoveInvalidUtf8Sequences(s).c_str());
152+
}
153+
154+
inline jstring SafeNewStringUTF(JNIEnv *env, const char *s) {
155+
if (!s) return env->NewStringUTF("");
156+
return SafeNewStringUTF(env, std::string(s));
157+
}
158+
145159
// Template function for non-void return types
146160
template <typename Func, typename ReturnType>
147161
ReturnType SafeJNI(JNIEnv *env, const char *functionName, Func func,

sherpa-onnx/jni/keyword-spotter.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ JNIEXPORT jobject JNICALL Java_com_k2fsa_sherpa_onnx_KeywordSpotter_getResult(
189189

190190
sherpa_onnx::KeywordResult result = kws->GetResult(stream);
191191

192-
jstring j_keyword = env->NewStringUTF(result.keyword.c_str());
192+
jstring j_keyword = SafeNewStringUTF(env, result.keyword);
193193

194194
// Convert tokens (std::vector<std::string> -> String[])
195195
jclass string_cls = env->FindClass("java/lang/String");
@@ -203,7 +203,7 @@ JNIEXPORT jobject JNICALL Java_com_k2fsa_sherpa_onnx_KeywordSpotter_getResult(
203203
env->NewObjectArray(result.tokens.size(), string_cls, nullptr);
204204

205205
for (size_t i = 0; i < result.tokens.size(); ++i) {
206-
jstring t = env->NewStringUTF(result.tokens[i].c_str());
206+
jstring t = SafeNewStringUTF(env, result.tokens[i]);
207207
env->SetObjectArrayElement(j_tokens, i, t);
208208
env->DeleteLocalRef(t);
209209
}

sherpa-onnx/jni/offline-punctuation.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,5 @@ Java_com_k2fsa_sherpa_onnx_OfflinePunctuation_addPunctuation(JNIEnv *env,
117117

118118
env->ReleaseStringUTFChars(text, ptext);
119119

120-
return env->NewStringUTF(result.c_str());
120+
return SafeNewStringUTF(env, result);
121121
}

sherpa-onnx/jni/offline-recognizer.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -645,15 +645,15 @@ Java_com_k2fsa_sherpa_onnx_OfflineRecognizer_getResult(JNIEnv *env,
645645
env->GetMethodID(cls, "<init>",
646646
"(Ljava/lang/String;[Ljava/lang/String;[FLjava/lang/"
647647
"String;Ljava/lang/String;Ljava/lang/String;[F)V");
648-
jstring jtext = env->NewStringUTF(result.text.c_str());
648+
jstring jtext = SafeNewStringUTF(env, result.text);
649649

650650
jclass string_cls = env->FindClass("java/lang/String");
651651
jobjectArray jtokens =
652652
env->NewObjectArray(result.tokens.size(), string_cls, nullptr);
653653
env->DeleteLocalRef(string_cls);
654654

655655
for (size_t i = 0; i < result.tokens.size(); ++i) {
656-
jstring token_str = env->NewStringUTF(result.tokens[i].c_str());
656+
jstring token_str = SafeNewStringUTF(env, result.tokens[i]);
657657
env->SetObjectArrayElement(jtokens, i, token_str);
658658
env->DeleteLocalRef(token_str);
659659
}
@@ -662,9 +662,9 @@ Java_com_k2fsa_sherpa_onnx_OfflineRecognizer_getResult(JNIEnv *env,
662662
env->SetFloatArrayRegion(jtimestamps, 0, result.timestamps.size(),
663663
result.timestamps.data());
664664

665-
jstring jlang = env->NewStringUTF(result.lang.c_str());
666-
jstring jemotion = env->NewStringUTF(result.emotion.c_str());
667-
jstring jevent = env->NewStringUTF(result.event.c_str());
665+
jstring jlang = SafeNewStringUTF(env, result.lang);
666+
jstring jemotion = SafeNewStringUTF(env, result.emotion);
667+
jstring jevent = SafeNewStringUTF(env, result.event);
668668

669669
jfloatArray jdurations = env->NewFloatArray(result.durations.size());
670670
env->SetFloatArrayRegion(jdurations, 0, result.durations.size(),

sherpa-onnx/jni/offline-stream.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ JNIEXPORT jstring JNICALL Java_com_k2fsa_sherpa_onnx_OfflineStream_getOption(
4242
const char *p_key = env->GetStringUTFChars(key, nullptr);
4343
const std::string &value = stream->GetOption(p_key);
4444
env->ReleaseStringUTFChars(key, p_key);
45-
return env->NewStringUTF(value.c_str());
45+
return SafeNewStringUTF(env, value);
4646
}
4747

4848
SHERPA_ONNX_EXTERN_C

sherpa-onnx/jni/online-punctuation.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,5 @@ Java_com_k2fsa_sherpa_onnx_OnlinePunctuation_addPunctuation(JNIEnv *env,
122122

123123
env->ReleaseStringUTFChars(text, ptext);
124124

125-
return env->NewStringUTF(result.c_str());
125+
return SafeNewStringUTF(env, result);
126126
}

sherpa-onnx/jni/online-recognizer.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,15 +407,15 @@ JNIEXPORT jobject JNICALL Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_getResult(
407407
cls, "<init>", "(Ljava/lang/String;[Ljava/lang/String;[F[F)V");
408408

409409
// text
410-
jstring text = env->NewStringUTF(result.text.c_str());
410+
jstring text = SafeNewStringUTF(env, result.text);
411411

412412
// tokens
413413
jclass string_cls = env->FindClass("java/lang/String");
414414
jobjectArray tokens =
415415
env->NewObjectArray(result.tokens.size(), string_cls, nullptr);
416416
env->DeleteLocalRef(string_cls);
417417
for (size_t i = 0; i < result.tokens.size(); ++i) {
418-
jstring token_str = env->NewStringUTF(result.tokens[i].c_str());
418+
jstring token_str = SafeNewStringUTF(env, result.tokens[i]);
419419
env->SetObjectArrayElement(tokens, i, token_str);
420420
env->DeleteLocalRef(token_str);
421421
}

sherpa-onnx/jni/online-stream.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ JNIEXPORT jstring JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_getOption(
4949
const char *p_key = env->GetStringUTFChars(key, nullptr);
5050
const std::string &value = stream->GetOption(p_key);
5151
env->ReleaseStringUTFChars(key, p_key);
52-
return env->NewStringUTF(value.c_str());
52+
return SafeNewStringUTF(env, value);
5353
}
5454

5555
SHERPA_ONNX_EXTERN_C

sherpa-onnx/jni/speaker-embedding-manager.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,14 @@ Java_com_k2fsa_sherpa_onnx_SpeakerEmbeddingManager_search(JNIEnv *env,
139139
jclass iae = env->FindClass("java/lang/IllegalArgumentException");
140140
env->ThrowNew(iae, "Embedding dimension mismatch");
141141
env->DeleteLocalRef(iae);
142-
return env->NewStringUTF("");
142+
return SafeNewStringUTF(env, "");
143143
}
144144

145145
std::string name = manager->Search(p, threshold);
146146

147147
env->ReleaseFloatArrayElements(embedding, p, JNI_ABORT);
148148

149-
return env->NewStringUTF(name.c_str());
149+
return SafeNewStringUTF(env, name);
150150
}
151151

152152
SHERPA_ONNX_EXTERN_C
@@ -220,7 +220,7 @@ Java_com_k2fsa_sherpa_onnx_SpeakerEmbeddingManager_allSpeakerNames(
220220

221221
int32_t i = 0;
222222
for (auto &s : all_speakers) {
223-
jstring js = env->NewStringUTF(s.c_str());
223+
jstring js = SafeNewStringUTF(env, s);
224224
env->SetObjectArrayElement(obj_arr, i, js);
225225
env->DeleteLocalRef(js);
226226
++i;

0 commit comments

Comments
 (0)