I want to get a struct tm from a const char *. In order to achieve the goal I use following code:
CCLog("ServerTimeStamp:%s",servertimestamp);
struct tm servertime;
servertime.tm_isdst=0;
servertime.tm_gmtoff=0;
CCLog("servertime prev:{%i,%i,%i,%i:%i:%i+%i+%li}",servertime.tm_year,servertime.tm_mon,servertime.tm_mday,servertime.tm_hour,servertime.tm_min,servertime.tm_sec,servertime.tm_isdst,servertime.tm_gmtoff);
strptime(servertimestamp, "%FT%TZ", &servertime);
CCLog("servertime post:{%i,%i,%i,%i:%i:%i+%i+%li}",servertime.tm_year,servertime.tm_mon,servertime.tm_mday,servertime.tm_hour,servertime.tm_min,servertime.tm_sec,servertime.tm_isdst,servertime.tm_gmtoff);
But the output is:
ServerTimeStamp:2014-07-18T11:51:09Z
servertime prev:{24,1803363120,22,1803363016:0:1796668624+0+0}
servertime post:{24,1803363120,22,1803363016:0:1796668624+0+0}
Which means that strptime has probably done nothing. Is this function not implemented on Android under JNI (In the cocos2d-x environment, version 2.1rc0-x-2.1.4)? What would be a suitable alternative? How can I convert the const char * to struct tm?
My App is cross-platform, and the same code works perfectly under iOS (also with the environment cocos2d-x, version 2.1rc0-x-2.1.4).
Thanks in advance!
Don't use the %F specifier for a date.
Related
I am interested in demoing printf vulnerabilities via an NDK app. To be clear, I am aware that to log in the console we can use __android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "Print : %d %s",someVal, someStr);. I have tried it and I know it works. But I explicitly want to demo the vulnerabilities of printf(), specifically to use the %n specifier to write to a pointed location.
Is there a way to make printf() work to this effect or is it possible to achieve this via __android_log_print()? I attempted it with the android/log.h header but it didn't work.
I can get the app to crash by running something along the lines of printf(%s%s%s%s%s%s%s%s%s%s). But again, I can't manipulate pointers.
For general knowledge purposes, why is it that printf() doesn't work in the first place and how does __android_log_print() prevent these exploits?
You do realize that Android is open source.
Starting with looking for __android_log_print()
and finding it: https://android.googlesource.com/platform/system/core/+/refs/heads/master/liblog/logger_write.cpp
int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
va_list ap;
char buf[LOG_BUF_SIZE];
va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);
return __android_log_write(prio, tag, buf);
}
I eventually ended up looking at: https://android.googlesource.com/platform/bionic/+/refs/heads/master/libc/stdio/vfprintf.cpp
lines 453-454:
case 'n':
__fortify_fatal("%%n not allowed on Android");
Also referenced in the code is additional safety through FORTIFY which is described in the following blog post:
https://android-developers.googleblog.com/2017/04/fortify-in-android.html
Android specifically does not support %n format specifiers because they're vulnerable.
https://android.googlesource.com/platform/bionic/+/400b073ee38ecc2a38234261b221e3a7afc0498e/tests/stdio_test.cpp#328
I'm calling native function from Java:
String pathTemp = Environment.getExternalStorageDirectory().getAbsolutePath()+Const.PATH_TEMP
String pathFiles = Environment.getExternalStorageDirectory().getAbsolutePath()+Const.PATH_FILES
engine.init(someInt, pathTemp, pathFiles);
And I have the native function:
extern "C" JNIEXPORT void Java_com_engine_init(JNIEnv *env, jobject __unused obj, jint someInt, jstring pathTemp, jstring pathFiles) {
const char *pathTemp_ = env->GetStringUTFChars(pathTemp, JNI_FALSE);
const char *pathFiles_ = env->GetStringUTFChars(pathFiles, JNI_FALSE); // <-- CRASH
// More init code
env->ReleaseStringUTFChars(pathTemp, pathTemp_);
env->ReleaseStringUTFChars(pathRecording, pathRecording_);
}
The problem: pathTemp is arriving good, but pathFiles==NULL in native function.
Rechecked, and confirmed - both strings are non NULL in java.
One more strange thing - The problem is on LG-G3 (android 6.0).
On Meizu PRO 5 (android 7.0) - everything works good - both strings are intact.
What is this JNI magic? Any clue?
I had the same problem as this and while I can't guarantee this is the same, I found a better solution than re-ordering the parameters.
tldr; Ensure the code works for 32bit and 64bit platforms as pointers have different sizes. I was running 32bit native code and passed nullptr as a parameter and java expected a long which resulted in all parameters after the nullptr to be invalid.
(JJLjava/lang/String;Z)V -> (final long pCallback, final long pUserPointer, final String id, final boolean b)
pCallback was always set to a valid value (pointer casted to jlong in c++) and pUserPointer was always nullptr. I found this answer and tried switching the order around and it 'just worked' but I knew that fix was never going to be approved.
After looking at the JNI documentation on the Android website again (https://developer.android.com/training/articles/perf-jni) I took note of the "64-bit considerations" section and took a stab at my assumption of the data size. This feature was developed with a 64bit device (Pixel 3) but issues had been reported on a 32bit device (Amazon Fire Phone) so nullptr would be 32bit but the java function still expected a long (64bit).
In my situation the offending parameter was always unused so I could safely remove it and everything "just worked" (including some other parameters which were broken).
An alternative would be to have a define/function/macro for JniLongNullptr which is just 0 casted to jlong.
Not an answer, but workaround. Moved the strings (in parameters) to be before int parameter. Now it's working. I have no idea why is this.
I have spent a ridiculous amount of time trying to figure this out and I am at an absolute loss.
I am working with the JUCE library and have modified one of their sample projects. My goal is to have a very simple Android app that is written in C++ and then ported to Android. I need a function in C++ that I can call that will then call a function on the Android side that will return my heap size and other characteristics to my C++ code so that I can manage memory there.
If anyone has a simple solution that would be amazing. Right now my current snag is this:
char const buf[] = "From JNI";
jstring jstr = env->NewStringUTF(buf);
jclass clazz = env->FindClass("android/os/Debug");
But I keep getting an error saying that 'NewStringUTF' is not a _JNIEnv member... but if I right click on the method and jump to the definition, I see it in my jni.h file... any suggestions? I'm working in Xcode by the way...
Is it plain C, not C++? Perhaps your file has a .c extension.
If it's plain C it should be
JNIEnv* env;
JNI_CreateJavaVM(&jvm, (void **)&env, &args);
(*env)->NewStringUTF(env, buf);
I have a function like
__android_log_print(ANDROID_LOG_INFO, "HelloNDK!");
on my C code
I wouldn't find that output on my LogCat. What kind of filter I need to setup
by Log Tag, by Log Message, by Application Name, by Log Level...etc.
You don't find output because you have misused the function. The function has the prototype:
int __android_log_print(int prio, const char *tag, const char *fmt, ...);
So you must supply a "tag" as well as the format.
For example
__android_log_print(ANDROID_LOG_INFO, "MyTag", "The value is %d", some_variable);
Once you use the function properly, you can use any filtering method (or none at all - such as you'd get from the adb logcat command without further arguments) just as with java code.
Now I got a .so file and a C++ header file.
There is a function as follows:
BOOL __stdcall HK_STD_CreateHandle(IN PBYTE pFileHdrBuffer, IN DWORD dwFileHdrSize, IN DWORD dwBufferSize, OUT HANDLE& hHandle);
typedef BYTE * PBYTE;
typedef unsigned long DWORD;
typedef void * HANDLE;
I think I can implement a Java class to use the .so file:
public class Decoder {
static {
System.loadLibrary("SingleDecode");
}
public native boolean HK_STD_CreateHandle(
byte[] pFileHdrBuffer,
int dwFileHdrSize,
int dwBufferSize,
int hHandle);
}
But I don't know how to write the native function. Can anybody help me?
First of all your native function must have a certain name. For example, if you have a class MyActivity in the package com.android.test where you have declared the native method, the corresponding native function must be named:
Java_com_android_test_MyActivity_functionName();
Next, the native function must receive two additional arguments that are not explicitly defind by you (they're sent by the Java environment). I could explain it here, but it's probably easiest if you read up on JNI. Try Wikipedia for example:
http://en.wikipedia.org/wiki/Java_Native_Interface
There are also a few samples that comes with the NDK that will help you out.