Correctly set i and fsize after substitution, fix crash and code cleanup #2

Merged
SKBotNL merged 5 commits from main into main 2026-04-05 12:31:19 -04:00
7 changed files with 587 additions and 542 deletions

No files matched your search

+98 -96
View File
@@ -11,117 +11,119 @@ und_close0_t und_real_close0 = NULL;
fdi_read0_t fdi_real_read0 = NULL;
struct fdi_file_data {
char* data;
size_t index;
size_t length;
int freed;
size_t inode;
size_t device;
char *data;
size_t index;
size_t length;
int freed;
size_t inode;
size_t device;
};
struct file {
jint key;
struct fdi_file_data value;
jint key;
struct fdi_file_data value;
} *fdi_files_map = NULL;
jint JNICALL und_open0_hook(JNIEnv *env, jobject thiz, jlong path_address, jint flags, jint mode) {
jint fd = und_real_open0(env, thiz, path_address, flags, mode);
const char *path = (const char *)(intptr_t)path_address;
if (!path || !is_config_path(path)) {
return fd;
}
struct stat st;
if (fstat(fd, &st) != 0) {
jclass fileNotFoundException =
(*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return fd;
}
size_t fsize = st.st_size;
FILE *file = fopen(path, "rb");
if (!file) {
jclass fileNotFoundException =
(*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return fd;
}
char *data = malloc(fsize + 1);
fread(data, fsize, 1, file);
fclose(file);
data[fsize] = '\0';
parse_file(&data, fsize, path);
size_t fd_len = strlen(data);
struct fdi_file_data file_data;
file_data.data = data;
file_data.length = fd_len;
file_data.index = 0;
file_data.freed = 0;
file_data.inode = st.st_ino;
file_data.device = st.st_dev;
hmput(fdi_files_map, fd, file_data);
jint JNICALL und_open0_hook(JNIEnv *env, jobject thiz, jlong path_address,
jint flags, jint mode) {
jint fd = und_real_open0(env, thiz, path_address, flags, mode);
const char *path = (const char *)(intptr_t)path_address;
if (!path || !is_config_path(path)) {
return fd;
}
struct stat st;
if (fstat(fd, &st) != 0) {
jclass fileNotFoundException =
(*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return fd;
}
size_t fsize = st.st_size;
FILE *file = fopen(path, "rb");
if (!file) {
jclass fileNotFoundException =
(*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return fd;
}
char *data = malloc(fsize + 1);
fread(data, fsize, 1, file);
fclose(file);
data[fsize] = '\0';
parse_file(&data, fsize, path);
size_t fd_len = strlen(data);
struct fdi_file_data file_data;
file_data.data = data;
file_data.length = fd_len;
file_data.index = 0;
file_data.freed = 0;
file_data.inode = st.st_ino;
file_data.device = st.st_dev;
hmput(fdi_files_map, fd, file_data);
return fd;
}
void JNICALL und_close0_hook(JNIEnv* env, jobject thiz, jint fd) {
struct file *file = hmgetp_null(fdi_files_map, fd);
if (file != NULL) {
free(file->value.data);
file->value.data = NULL;
hmdel(fdi_files_map, fd);
}
void JNICALL und_close0_hook(JNIEnv *env, jobject thiz, jint fd) {
struct file *file = hmgetp_null(fdi_files_map, fd);
if (file != NULL) {
free(file->value.data);
file->value.data = NULL;
hmdel(fdi_files_map, fd);
}
}
jint JNICALL fdi_read0_hook(JNIEnv *env, jobject thiz, jobject fdObject, jlong address, jint len) {
jclass class = (*env)->GetObjectClass(env, fdObject);
jfieldID fieldID = (*env)->GetFieldID(env, class, "fd", "I");
jint fd = (*env)->GetIntField(env, fdObject, fieldID);
jint JNICALL fdi_read0_hook(JNIEnv *env, jobject thiz, jobject fdObject,
jlong address, jint len) {
jclass class = (*env)->GetObjectClass(env, fdObject);
jfieldID fieldID = (*env)->GetFieldID(env, class, "fd", "I");
jint fd = (*env)->GetIntField(env, fdObject, fieldID);
struct file *file = hmgetp_null(fdi_files_map, fd);
if (file == NULL) {
return fdi_real_read0(env, thiz, fdObject, address, len);
}
struct fdi_file_data *file_data = &file->value;
struct stat st;
if (fstat(fd, &st) != 0) {
hmdel(fdi_files_map, fd);
return fdi_real_read0(env, thiz, fdObject, address, len);
}
struct file *file = hmgetp_null(fdi_files_map, fd);
if (file == NULL) {
return fdi_real_read0(env, thiz, fdObject, address, len);
}
// Check if it's still the same file
if (st.st_ino != file_data->inode || st.st_dev != file_data->device) {
hmdel(fdi_files_map, fd);
return fdi_real_read0(env, thiz, fdObject, address, len);
}
struct fdi_file_data *file_data = &file->value;
struct stat st;
if (fstat(fd, &st) != 0) {
hmdel(fdi_files_map, fd);
return fdi_real_read0(env, thiz, fdObject, address, len);
}
if (file_data->freed) {
return -1;
}
// Check if it's still the same file
if (st.st_ino != file_data->inode || st.st_dev != file_data->device) {
hmdel(fdi_files_map, fd);
return fdi_real_read0(env, thiz, fdObject, address, len);
}
if (file_data->length == 0) {
free(file_data->data);
file_data->data = NULL;
file_data->freed = 1;
return -1;
}
if (file_data->freed) {
return -1;
}
int n = MIN(len, file_data->length - file_data->index);
memcpy((void *)(intptr_t)address, file_data->data + file_data->index, n);
if (file_data->length == 0) {
free(file_data->data);
file_data->data = NULL;
file_data->freed = 1;
return -1;
}
if (n == file_data->length - file_data->index) {
free(file_data->data);
file_data->data = NULL;
file_data->freed = 1;
} else {
file_data->index += n;
}
int n = MIN(len, file_data->length - file_data->index);
memcpy((void *)(intptr_t)address, file_data->data + file_data->index, n);
return n;
if (n == file_data->length - file_data->index) {
free(file_data->data);
file_data->data = NULL;
file_data->freed = 1;
} else {
file_data->index += n;
}
return n;
}
+6 -6
View File
@@ -3,17 +3,17 @@
#include <jvmti.h>
typedef jint (JNICALL *und_open0_t)(JNIEnv*, jobject, jlong, jint, jint);
typedef jint(JNICALL *und_open0_t)(JNIEnv *, jobject, jlong, jint, jint);
extern und_open0_t und_real_open0;
typedef jint (JNICALL *und_close0_t)(JNIEnv*, jobject, jint);
typedef jint(JNICALL *und_close0_t)(JNIEnv *, jobject, jint);
extern und_close0_t und_real_close0;
typedef jint (JNICALL *fdi_read0_t)(JNIEnv*, jobject, jobject, jlong, jint);
typedef jint(JNICALL *fdi_read0_t)(JNIEnv *, jobject, jobject, jlong, jint);
extern fdi_read0_t fdi_real_read0;
jint JNICALL und_open0_hook(JNIEnv*, jobject, jlong, jint, jint);
void JNICALL und_close0_hook(JNIEnv*, jobject, jint);
jint JNICALL und_open0_hook(JNIEnv *, jobject, jlong, jint, jint);
void JNICALL und_close0_hook(JNIEnv *, jobject, jint);
jint JNICALL fdi_read0_hook(JNIEnv*, jobject, jobject, jlong, jint);
jint JNICALL fdi_read0_hook(JNIEnv *, jobject, jobject, jlong, jint);
#endif
+229 -219
View File
@@ -15,239 +15,249 @@ fis_available0_t fis_real_available0 = NULL;
fis_close_t fis_real_close = NULL;
struct fis_file_data {
char* data;
size_t index;
size_t length;
int freed;
char *data;
size_t index;
size_t length;
int freed;
};
struct file{
jint key;
struct fis_file_data value;
struct file {
jint key;
struct fis_file_data value;
} *fis_files_map = NULL;
jint JNICALL fis_readBytes_hook(JNIEnv* env, jobject thiz, jbyteArray buf, jint off, jint len) {
if (!has_tag(thiz)) {
return fis_real_readBytes(env, thiz, buf, off, len);
}
jint JNICALL fis_readBytes_hook(JNIEnv *env, jobject thiz, jbyteArray buf,
jint off, jint len) {
if (!has_tag(thiz)) {
return fis_real_readBytes(env, thiz, buf, off, len);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL || file->value.freed) {
return -1;
}
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL || file->value.freed) {
return -1;
}
struct fis_file_data *fd = &file->value;
jsize ba_length = (*env)->GetArrayLength(env, buf);
jbyte *ba = (*env)->GetByteArrayElements(env, buf, JNI_FALSE);
struct fis_file_data *fd = &file->value;
jsize ba_length = (*env)->GetArrayLength(env, buf);
jbyte *ba = (*env)->GetByteArrayElements(env, buf, JNI_FALSE);
size_t remaining = fd->length - fd->index;
jsize len_want_to_read = MIN((ba_length - off), len);
jsize len_to_read = MIN(len_want_to_read, (jsize)remaining);
if (len_to_read < 0) {
(*env)->ReleaseByteArrayElements(env, buf, ba, 0);
return -1;
}
memcpy(ba + off, fd->data + fd->index, len_to_read);
size_t remaining = fd->length - fd->index;
jsize len_want_to_read = MIN((ba_length - off), len);
jsize len_to_read = MIN(len_want_to_read, (jsize)remaining);
if (len_to_read < 0) {
(*env)->ReleaseByteArrayElements(env, buf, ba, 0);
return -1;
}
memcpy(ba + off, fd->data + fd->index, len_to_read);
fd->index += len_to_read;
if (fd->index == fd->length) {
free(fd->data);
fd->data = NULL;
fd->freed = 1;
}
(*env)->ReleaseByteArrayElements(env, buf, ba, 0);
return len_to_read;
fd->index += len_to_read;
if (fd->index == fd->length) {
free(fd->data);
fd->data = NULL;
fd->freed = 1;
}
return len_to_read;
}
void JNICALL fis_open0_hook(JNIEnv* env, jobject thiz, jstring jpath) {
if (has_tag(thiz)) {
return;
}
const char* path = (*env)->GetStringUTFChars(env, jpath, NULL);
if (!path || !is_config_path(path)) {
fis_real_open0(env, thiz, jpath);
return;
}
tag(thiz);
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
FILE *file = fopen(path, "rb");
if (!file) {
jclass fileNotFoundException = (*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return;
}
struct stat st;
if (fstat(fileno(file), &st) != 0) {
jclass fileNotFoundException =
(*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return;
}
size_t fsize = st.st_size;
if (fsize == 0) {
fclose(file);
return;
}
char *data = malloc(fsize + 1);
fread(data, fsize, 1, file);
fclose(file);
data[fsize] = '\0';
parse_file(&data, fsize, path);
size_t fd_len = strlen(data);
struct fis_file_data file_data;
file_data.data = data;
file_data.length = fd_len;
file_data.index = 0;
file_data.freed = 0;
hmput(fis_files_map, hash, file_data);
(*env)->ReleaseStringUTFChars(env, jpath, path);
}
jint JNICALL fis_read0_hook(JNIEnv* env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_read0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL || file->value.freed) {
return -1;
}
struct fis_file_data *fd = &file->value;
char read_byte = fd->data[fd->index++];
if (fd->data[fd->index] == '\0') {
free(fd->data);
fd->data = NULL;
fd->freed = 1;
}
return read_byte;
}
jlong JNICALL fis_length0_hook(JNIEnv* env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_length0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return -1;
}
return file->value.length;
}
jlong JNICALL fis_position0_hook(JNIEnv* env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_length0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return -1;
}
return file->value.index;
}
jlong JNICALL fis_skip0_hook(JNIEnv* env, jobject thiz, jlong n) {
if (!has_tag(thiz)) {
return fis_real_skip0(env, thiz, n);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return 0;
}
struct fis_file_data *fd = &file->value;
size_t remaining = fd->length - fd->index;
size_t skip = MIN(remaining, n);
fd->index += skip;
if (skip == remaining) {
free(fd->data);
fd->data = NULL;
fd->freed = 1;
return skip;
}
return skip;
}
jint JNICALL fis_available0_hook(JNIEnv* env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_available0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return 0;
}
struct fis_file_data *fd = &file->value;
return fd->length - fd->index;
}
void JNICALL fis_close_hook(JNIEnv* env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_close(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method = (*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return;
}
free(file->value.data);
file->value.data = NULL;
file->value.freed = 1;
void JNICALL fis_open0_hook(JNIEnv *env, jobject thiz, jstring jpath) {
if (has_tag(thiz)) {
return;
}
const char *path = (*env)->GetStringUTFChars(env, jpath, NULL);
if (!path || !is_config_path(path)) {
fis_real_open0(env, thiz, jpath);
return;
}
tag(thiz);
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
FILE *file = fopen(path, "rb");
if (!file) {
jclass fileNotFoundException =
(*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return;
}
struct stat st;
if (fstat(fileno(file), &st) != 0) {
jclass fileNotFoundException =
(*env)->FindClass(env, "java/io/FileNotFoundException");
(*env)->ThrowNew(env, fileNotFoundException, path);
return;
}
size_t fsize = st.st_size;
if (fsize == 0) {
fclose(file);
return;
}
char *data = malloc(fsize + 1);
fread(data, fsize, 1, file);
fclose(file);
data[fsize] = '\0';
parse_file(&data, fsize, path);
size_t fd_len = strlen(data);
struct fis_file_data file_data;
file_data.data = data;
file_data.length = fd_len;
file_data.index = 0;
file_data.freed = 0;
hmput(fis_files_map, hash, file_data);
(*env)->ReleaseStringUTFChars(env, jpath, path);
}
jint JNICALL fis_read0_hook(JNIEnv *env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_read0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL || file->value.freed) {
return -1;
}
struct fis_file_data *fd = &file->value;
char read_byte = fd->data[fd->index++];
if (fd->data[fd->index] == '\0') {
free(fd->data);
fd->data = NULL;
fd->freed = 1;
}
return read_byte;
}
jlong JNICALL fis_length0_hook(JNIEnv *env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_length0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return -1;
}
return file->value.length;
}
jlong JNICALL fis_position0_hook(JNIEnv *env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_length0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return -1;
}
return file->value.index;
}
jlong JNICALL fis_skip0_hook(JNIEnv *env, jobject thiz, jlong n) {
if (!has_tag(thiz)) {
return fis_real_skip0(env, thiz, n);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return 0;
}
struct fis_file_data *fd = &file->value;
size_t remaining = fd->length - fd->index;
size_t skip = MIN(remaining, n);
fd->index += skip;
if (skip == remaining) {
free(fd->data);
fd->data = NULL;
fd->freed = 1;
return skip;
}
return skip;
}
jint JNICALL fis_available0_hook(JNIEnv *env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_available0(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return 0;
}
struct fis_file_data *fd = &file->value;
return fd->length - fd->index;
}
void JNICALL fis_close_hook(JNIEnv *env, jobject thiz) {
if (!has_tag(thiz)) {
return fis_real_close(env, thiz);
}
jclass class = (*env)->GetObjectClass(env, thiz);
jmethodID hash_code_method =
(*env)->GetMethodID(env, class, "hashCode", "()I");
jint hash = (*env)->CallIntMethod(env, thiz, hash_code_method);
struct file *file = hmgetp_null(fis_files_map, hash);
if (file == NULL) {
return;
}
free(file->value.data);
file->value.data = NULL;
file->value.freed = 1;
return;
}
+18 -16
View File
@@ -3,14 +3,15 @@
#include <jvmti.h>
typedef void (JNICALL *fis_open0_t)(JNIEnv*, jobject, jstring);
typedef jint (JNICALL *fis_readBytes_t)(JNIEnv*, jobject, jbyteArray, jint, jint);
typedef jint (JNICALL *fis_read0_t)(JNIEnv*, jobject);
typedef jlong (JNICALL *fis_length0_t)(JNIEnv*, jobject);
typedef jlong (JNICALL *fis_position0_t)(JNIEnv*, jobject);
typedef jlong (JNICALL *fis_skip0_t)(JNIEnv*, jobject, jlong);
typedef jint (JNICALL *fis_available0_t)(JNIEnv*, jobject);
typedef void (JNICALL *fis_close_t)(JNIEnv*, jobject);
typedef void(JNICALL *fis_open0_t)(JNIEnv *, jobject, jstring);
typedef jint(JNICALL *fis_readBytes_t)(JNIEnv *, jobject, jbyteArray, jint,
jint);
typedef jint(JNICALL *fis_read0_t)(JNIEnv *, jobject);
typedef jlong(JNICALL *fis_length0_t)(JNIEnv *, jobject);
typedef jlong(JNICALL *fis_position0_t)(JNIEnv *, jobject);
typedef jlong(JNICALL *fis_skip0_t)(JNIEnv *, jobject, jlong);
typedef jint(JNICALL *fis_available0_t)(JNIEnv *, jobject);
typedef void(JNICALL *fis_close_t)(JNIEnv *, jobject);
extern fis_readBytes_t fis_real_readBytes;
extern fis_open0_t fis_real_open0;
extern fis_read0_t fis_real_read0;
@@ -20,13 +21,14 @@ extern fis_skip0_t fis_real_skip0;
extern fis_available0_t fis_real_available0;
extern fis_close_t fis_real_close;
jint JNICALL fis_readBytes_hook(JNIEnv* env, jobject thiz, jbyteArray buf, jint off, jint len);
void JNICALL fis_open0_hook(JNIEnv* env, jobject thiz, jstring jpath);
jint JNICALL fis_read0_hook(JNIEnv* env, jobject thiz);
jlong JNICALL fis_length0_hook(JNIEnv* env, jobject thiz);
jlong JNICALL fis_position0_hook(JNIEnv* env, jobject thiz);
jlong JNICALL fis_skip0_hook(JNIEnv* env, jobject thiz, jlong n);
jint JNICALL fis_available0_hook(JNIEnv* env, jobject thiz);
void JNICALL fis_close_hook(JNIEnv* env, jobject thiz);
jint JNICALL fis_readBytes_hook(JNIEnv *env, jobject thiz, jbyteArray buf,
jint off, jint len);
void JNICALL fis_open0_hook(JNIEnv *env, jobject thiz, jstring jpath);
jint JNICALL fis_read0_hook(JNIEnv *env, jobject thiz);
jlong JNICALL fis_length0_hook(JNIEnv *env, jobject thiz);
jlong JNICALL fis_position0_hook(JNIEnv *env, jobject thiz);
jlong JNICALL fis_skip0_hook(JNIEnv *env, jobject thiz, jlong n);
jint JNICALL fis_available0_hook(JNIEnv *env, jobject thiz);
void JNICALL fis_close_hook(JNIEnv *env, jobject thiz);
#endif
+128 -118
View File
@@ -1,142 +1,152 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "build_info.h"
#include "fdi_hook.h"
#include "fis_hook.h"
#include "utils.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
static void JNICALL onNativeMethodBind(jvmtiEnv* jvmti_env, JNIEnv* env, jthread thread, jmethodID method, void* address, void** new_address_ptr) {
char* mname = NULL;
char* msig = NULL;
char* csig = NULL;
char* gsig = NULL;
static void JNICALL onNativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv *env,
jthread thread, jmethodID method,
void *address, void **new_address_ptr) {
char *mname = NULL;
char *msig = NULL;
char *csig = NULL;
char *gsig = NULL;
jclass decl;
(*jvmti_env)->GetMethodDeclaringClass(jvmti_env, method, &decl);
(*jvmti_env)->GetClassSignature(jvmti_env, decl, &csig, &gsig);
(*jvmti_env)->GetMethodName(jvmti_env, method, &mname, &msig, NULL);
jclass decl;
(*jvmti_env)->GetMethodDeclaringClass(jvmti_env, method, &decl);
(*jvmti_env)->GetClassSignature(jvmti_env, decl, &csig, &gsig);
(*jvmti_env)->GetMethodName(jvmti_env, method, &mname, &msig, NULL);
if (csig && mname && msig) {
if (strcmp(csig, "Ljava/io/FileInputStream;") == 0) {
// private native void open0(String name)
if (strcmp(mname, "open0") == 0 && strcmp(msig, "(Ljava/lang/String;)V") == 0) {
fis_real_open0 = (fis_open0_t)address;
*new_address_ptr = (void*)&fis_open0_hook;
// private native int readBytes(byte b[], int off, int len)
} else if (strcmp(mname, "readBytes") == 0 && strcmp(msig, "([BII)I") == 0) {
fis_real_readBytes = (fis_readBytes_t)address;
*new_address_ptr = (void*)&fis_readBytes_hook;
// private native int read0
} else if (strcmp(mname, "read0") == 0 && strcmp(msig, "()I") == 0) {
fis_real_read0 = (fis_read0_t)address;
*new_address_ptr = (void*)&fis_read0_hook;
// private native long length0()
} else if (strcmp(mname, "length0") == 0 && strcmp(msig, "()J") == 0) {
fis_real_length0 = (fis_length0_t)address;
*new_address_ptr = (void*)&fis_length0_hook;
// private native long position0()
} else if (strcmp(mname, "position0") == 0 && strcmp(msig, "()J") == 0) {
fis_real_position0 = (fis_position0_t)address;
*new_address_ptr = (void*)&fis_position0_hook;
// private native long skip0(long n)
} else if (strcmp(mname, "skip0") == 0 && strcmp(msig, "(J)J") == 0) {
fis_real_skip0 = (fis_skip0_t)address;
*new_address_ptr = (void*)&fis_skip0_hook;
// private native int available0()
} else if (strcmp(mname, "available0") == 0 && strcmp(msig, "()I") == 0) {
fis_real_available0 = (fis_available0_t)address;
*new_address_ptr = (void*)&fis_available0_hook;
// public void close()
} else if (strcmp(mname, "close") == 0 && strcmp(msig, "()V") == 0) {
fis_real_close = (fis_close_t)address;
*new_address_ptr = (void*)&fis_close_hook;
}
} else if (strcmp(csig, "Lsun/nio/fs/UnixNativeDispatcher;") == 0) {
// private static native int open0(long pathAddress, int flags, int mode)
if (strcmp(mname, "open0") == 0 && strcmp(msig, "(JII)I") == 0) {
und_real_open0 = (und_open0_t)address;
*new_address_ptr = (void*)&und_open0_hook;
// private static native void close0(int fd)
} else if (strcmp(mname, "close0") == 0 && strcmp(msig, "(I)V") == 0) {
und_real_close0 = (und_close0_t)address;
*new_address_ptr = (void*)&und_close0_hook;
}
} else if (strcmp(csig, "Lsun/nio/ch/FileDispatcherImpl;") == 0) {
// static native int read0(FileDescriptor fd, long address, int len)
if (strcmp(mname, "read0") == 0 && strcmp(msig, "(Ljava/io/FileDescriptor;JI)I") == 0) {
fdi_real_read0 = (fdi_read0_t)address;
*new_address_ptr = (void*)&fdi_read0_hook;
}
}
if (csig && mname && msig) {
if (strcmp(csig, "Ljava/io/FileInputStream;") == 0) {
// private native void open0(String name)
if (strcmp(mname, "open0") == 0 &&
strcmp(msig, "(Ljava/lang/String;)V") == 0) {
fis_real_open0 = (fis_open0_t)address;
*new_address_ptr = (void *)&fis_open0_hook;
// private native int readBytes(byte b[], int off, int len)
} else if (strcmp(mname, "readBytes") == 0 &&
strcmp(msig, "([BII)I") == 0) {
fis_real_readBytes = (fis_readBytes_t)address;
*new_address_ptr = (void *)&fis_readBytes_hook;
// private native int read0
} else if (strcmp(mname, "read0") == 0 && strcmp(msig, "()I") == 0) {
fis_real_read0 = (fis_read0_t)address;
*new_address_ptr = (void *)&fis_read0_hook;
// private native long length0()
} else if (strcmp(mname, "length0") == 0 && strcmp(msig, "()J") == 0) {
fis_real_length0 = (fis_length0_t)address;
*new_address_ptr = (void *)&fis_length0_hook;
// private native long position0()
} else if (strcmp(mname, "position0") == 0 && strcmp(msig, "()J") == 0) {
fis_real_position0 = (fis_position0_t)address;
*new_address_ptr = (void *)&fis_position0_hook;
// private native long skip0(long n)
} else if (strcmp(mname, "skip0") == 0 && strcmp(msig, "(J)J") == 0) {
fis_real_skip0 = (fis_skip0_t)address;
*new_address_ptr = (void *)&fis_skip0_hook;
// private native int available0()
} else if (strcmp(mname, "available0") == 0 && strcmp(msig, "()I") == 0) {
fis_real_available0 = (fis_available0_t)address;
*new_address_ptr = (void *)&fis_available0_hook;
// public void close()
} else if (strcmp(mname, "close") == 0 && strcmp(msig, "()V") == 0) {
fis_real_close = (fis_close_t)address;
*new_address_ptr = (void *)&fis_close_hook;
}
} else if (strcmp(csig, "Lsun/nio/fs/UnixNativeDispatcher;") == 0) {
// private static native int open0(long pathAddress, int flags, int mode)
if (strcmp(mname, "open0") == 0 && strcmp(msig, "(JII)I") == 0) {
und_real_open0 = (und_open0_t)address;
*new_address_ptr = (void *)&und_open0_hook;
// private static native void close0(int fd)
} else if (strcmp(mname, "close0") == 0 && strcmp(msig, "(I)V") == 0) {
und_real_close0 = (und_close0_t)address;
*new_address_ptr = (void *)&und_close0_hook;
}
} else if (strcmp(csig, "Lsun/nio/ch/FileDispatcherImpl;") == 0) {
// static native int read0(FileDescriptor fd, long address, int len)
if (strcmp(mname, "read0") == 0 &&
strcmp(msig, "(Ljava/io/FileDescriptor;JI)I") == 0) {
fdi_real_read0 = (fdi_read0_t)address;
*new_address_ptr = (void *)&fdi_read0_hook;
}
}
}
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)mname);
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)msig);
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)csig);
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)gsig);
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char *)mname);
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char *)msig);
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char *)csig);
(*jvmti_env)->Deallocate(jvmti_env, (unsigned char *)gsig);
}
static jint init_jvmti(JavaVM* vm) {
jint rc = (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_2);
if (rc != JNI_OK || jvmti == NULL) return JNI_ERR;
static jint init_jvmti(JavaVM *vm) {
jint rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1_2);
if (rc != JNI_OK || jvmti == NULL)
return JNI_ERR;
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
caps.can_generate_native_method_bind_events = 1;
caps.can_tag_objects = 1;
(*jvmti)->AddCapabilities(jvmti, &caps);
jvmtiCapabilities caps;
memset(&caps, 0, sizeof(caps));
caps.can_generate_native_method_bind_events = 1;
caps.can_tag_objects = 1;
(*jvmti)->AddCapabilities(jvmti, &caps);
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.NativeMethodBind = &onNativeMethodBind;
(*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.NativeMethodBind = &onNativeMethodBind;
(*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, (jthread)NULL);
(*jvmti)->SetEventNotificationMode(
jvmti, JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, (jthread)NULL);
FILE *env_file = fopen(".env", "r");
if (env_file) {
char* line = NULL;
size_t len = 0;
ssize_t n;
while ((n = getline(&line, &len, env_file)) != -1) {
if (n > 0 && line[n - 1] == '\n') {
line[n - 1] = '\0';
}
if (line[0] == '#') {
continue;
}
char *name = line;
char *value = NULL;
char *equal = strchr(line, '=');
if (equal == NULL) {
fprintf(stderr, "\e[0;31m[SubstAgent] Invalid line in .env: \"%s\"\e[0m\n", line);
continue;
}
*equal = '\0';
value = equal + 1;
if (setenv(name, value, 0) != 0) {
perror("[SubstAgent] setenv failed");
}
}
free(line);
fclose(env_file);
} else if (errno != ENOENT) {
perror("[SubstAgent] fopen failed");
exit(EXIT_FAILURE);
FILE *env_file = fopen(".env", "r");
if (env_file) {
char *line = NULL;
size_t len = 0;
ssize_t n;
while ((n = getline(&line, &len, env_file)) != -1) {
if (n > 0 && line[n - 1] == '\n') {
line[n - 1] = '\0';
}
if (line[0] == '#') {
continue;
}
char *name = line;
char *value = NULL;
char *equal = strchr(line, '=');
if (equal == NULL) {
fprintf(stderr,
"\e[0;31m[SubstAgent] Invalid line in .env: \"%s\"\e[0m\n",
line);
continue;
}
*equal = '\0';
value = equal + 1;
if (setenv(name, value, 0) != 0) {
perror("[SubstAgent] setenv failed");
}
}
free(line);
fclose(env_file);
} else if (errno != ENOENT) {
perror("[SubstAgent] fopen failed");
exit(EXIT_FAILURE);
}
fprintf(stderr, "[SubstAgent] Loaded version %s\n", GIT_HASH);
fprintf(stderr, "[SubstAgent] Loaded version %s\n", GIT_HASH);
return JNI_OK;
return JNI_OK;
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
return init_jvmti(vm);
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
return init_jvmti(vm);
}
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
return init_jvmti(vm);
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm, char *options,
void *reserved) {
return init_jvmti(vm);
}
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM* vm) {}
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {}
+103 -83
View File
@@ -3,101 +3,121 @@
#include <stdlib.h>
#include <string.h>
jvmtiEnv* jvmti = NULL;
jvmtiEnv *jvmti = NULL;
static const jlong TAG = 1;
void tag(jobject obj) {
if (obj && jvmti) {
(*jvmti)->SetTag(jvmti, obj, TAG);
}
if (obj && jvmti) {
(*jvmti)->SetTag(jvmti, obj, TAG);
}
}
int has_tag(jobject obj) {
jlong tag = 0;
if (obj && jvmti) {
(*jvmti)->GetTag(jvmti, obj, &tag);
}
return tag == 1;
jlong tag = 0;
if (obj && jvmti) {
(*jvmti)->GetTag(jvmti, obj, &tag);
}
return tag == 1;
}
int is_config_path(const char* path) {
char* extString = strrchr(path, '.');
if (extString) {
return strcmp(extString, ".yml") == 0 || strcmp(extString, ".yaml") == 0 || strcmp(extString, ".json") == 0 || strcmp(extString, ".txt") == 0 || strcmp(extString, ".properties") == 0;
}
return 0;
int is_config_path(const char *path) {
char *extString = strrchr(path, '.');
if (extString) {
return strcmp(extString, ".yml") == 0 || strcmp(extString, ".yaml") == 0 ||
strcmp(extString, ".json") == 0 || strcmp(extString, ".txt") == 0 ||
strcmp(extString, ".properties") == 0;
}
return 0;
}
char* substitute(const char* value, int dollar_sign_matched_index, size_t i, size_t env_len, const char *data) {
size_t value_len = strlen(value);
ssize_t len_diff = value_len - env_len;
size_t data_len = strlen(data);
size_t new_len = data_len+len_diff;
char* new_data = malloc(new_len + 1);
size_t after_len = new_len - dollar_sign_matched_index - value_len;
memcpy(new_data, data, dollar_sign_matched_index);
memcpy(new_data+dollar_sign_matched_index, value, value_len);
memcpy(new_data+dollar_sign_matched_index+value_len, data+i, after_len);
assert(dollar_sign_matched_index+value_len+after_len == new_len);
new_data[new_len] = '\0';
return new_data;
char *substitute(const char *value, int prefix_char_matched_index, size_t i,
size_t value_len, size_t len_diff, const char *data) {
size_t data_len = strlen(data);
size_t new_len = data_len + len_diff;
char *new_data = malloc(new_len + 1);
size_t after_len = new_len - prefix_char_matched_index - value_len;
memcpy(new_data, data, prefix_char_matched_index);
memcpy(new_data + prefix_char_matched_index, value, value_len);
memcpy(new_data + prefix_char_matched_index + value_len, data + i, after_len);
assert(prefix_char_matched_index + value_len + after_len == new_len);
new_data[new_len] = '\0';
return new_data;
}
void parse_file(char **data_ptr, size_t fsize, const char* filename) {
char *data = *data_ptr;
int line_count = 1;;
int begin_env_index = -1;
char env_var[4096];
env_var[0] = '\0';
for (size_t i = 0; i < fsize; i++) {
char c = data[i];
if (c == '\n') ++line_count;
if (begin_env_index != -1) {
if ((c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c == 95) {
size_t len = strlen(env_var);
env_var[len] = c;
env_var[len + 1] = '\0';
} else if (c == '}') {
if (strlen(env_var) == 0) {
begin_env_index = -1;
env_var[0] = '\0';
continue;
}
char* value = getenv(env_var);
if (!value) {
fprintf(stderr, "\033[0G\e[0;31m[SubstAgent] Failed to expand environment variable \"%s\" in file %s on line %d\e[0m\n", env_var, filename, line_count);
begin_env_index = -1;
env_var[0] = '\0';
continue;
}
// +1 for the closing }
size_t afterClosingTagIndex = i + 1;
size_t env_len = afterClosingTagIndex - begin_env_index;
char* new_data = substitute(value, begin_env_index, afterClosingTagIndex, env_len, data);
free(data);
data = new_data;
*data_ptr = new_data;
fprintf(stderr, "\033[0G[SubstAgent] Successfully expanded environment variable \"%s\" in file %s on line %d\n", env_var, filename, line_count);
begin_env_index = -1;
env_var[0] = '\0';
continue;
} else {
fprintf(stderr, "\033[0G\e[0;31m[SubstAgent] Invalid environment variable in file %s on line %d\e[0m\n", filename, line_count);
begin_env_index = -1;
env_var[0] = '\0';
}
} else {
if (c == '^') {
if (data[i+1] == '{') {
begin_env_index = i;
i++;
}
}
void parse_file(char **data_ptr, size_t fsize, const char *filename) {
char *data = *data_ptr;
int line_count = 1;
;
int begin_env_index = -1;
char env_var[4096];
env_var[0] = '\0';
for (size_t i = 0; i < fsize; i++) {
char c = data[i];
if (c == '\n')
++line_count;
if (begin_env_index != -1) {
if ((c >= 48 && c <= 57) || (c >= 65 && c <= 90) ||
(c >= 97 && c <= 122) || c == 95) {
size_t len = strlen(env_var);
env_var[len] = c;
env_var[len + 1] = '\0';
} else if (c == '}') {
if (strlen(env_var) == 0) {
begin_env_index = -1;
env_var[0] = '\0';
continue;
}
char *value = getenv(env_var);
if (!value) {
fprintf(stderr,
"\033[0G\e[0;31m[SubstAgent] Failed to expand environment "
"variable \"%s\" in file %s on line %d\e[0m\n",
env_var, filename, line_count);
begin_env_index = -1;
env_var[0] = '\0';
continue;
}
// +1 for the closing }
size_t after_closing_tag_index = i + 1;
size_t env_len = after_closing_tag_index - begin_env_index;
size_t value_len = strlen(value);
ssize_t len_diff = value_len - env_len;
char *new_data =
substitute(value, begin_env_index, after_closing_tag_index,
value_len, len_diff, data);
free(data);
data = new_data;
*data_ptr = new_data;
fprintf(stderr,
"\033[0G[SubstAgent] Successfully expanded environment "
"variable \"%s\" in file %s on line %d\n",
env_var, filename, line_count);
fsize += len_diff;
i += len_diff;
begin_env_index = -1;
env_var[0] = '\0';
continue;
} else {
fprintf(stderr,
"\033[0G\e[0;31m[SubstAgent] Invalid environment variable in "
"file %s on line %d\e[0m\n",
filename, line_count);
begin_env_index = -1;
env_var[0] = '\0';
}
} else {
if (c == '^') {
if (data[i + 1] == '{') {
begin_env_index = i;
i++;
}
}
}
}
}
+5 -4
View File
@@ -3,13 +3,14 @@
#include <jvmti.h>
extern jvmtiEnv* jvmti;
extern jvmtiEnv *jvmti;
void tag(jobject obj);
int has_tag(jobject obj);
int is_config_path(const char* path);
char* substitute(const char* value, int dollar_sign_matched_index, size_t i, size_t env_len, const char *data);
void parse_file(char **data_ptr, size_t fsize, const char* filename);
int is_config_path(const char *path);
char *substitute(const char *value, int dollar_sign_matched_index, size_t i,
size_t value_len, size_t len_diff, const char *data);
void parse_file(char **data_ptr, size_t fsize, const char *filename);
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))