Correctly set i and fsize after substitution, fix crash and code cleanup #2
No files matched your search
+98
-96
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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))
|
||||
|
||||
Reference in new issue
Block a user