corrupt EXIF header: maximum directory nesting level reached - php-5.3

While uploading some images, i get this error:
corrupt EXIF header: maximum directory nesting level reached
I'm trying to avoid the error by checking if response is false, but the error still happens.
$image = #imagecreatefromstring(file_get_contents($_FILES['fileinput']['tmp_name']));
$exif = #exif_read_data($_FILES['fileinput']['tmp_name'] ,'EXIF' ,0);
$rotation = 0;
if($exif !== false) {
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$rotation = 90;
break;
case 3:
$rotation = 180;
break;
case 6:
$rotation = 270;
break;
}
}
}
I get this error with just a few images. How can i track the error so i can skip header verification on the images that gives me the error?

There seem to be an issue with some EXIF data from some cameras like Fujifilm and some old php version. Check https://bugs.php.net/bug.php?id=66443
You may need to update php and maybe compile it from the source code.

Related

Why do builds for various projects fail with ‘Operation not permitted’ using iOS on-device compiler/toolchain?

I am an intermediately skilled Linux/Unix user trying to compile software for an iPad on a (jailbroken) iPad.
Many builds (for example, make and tex-live) fail with some Operation not permitted error. This will either look like Can't exec "blah": Operation not permitted or execvp: blah: Operation not permitted where blah is aclocal, a configure script, libtool, or just about anything. Curiously, finding the offending line in a Makefile or configure script and prefixing it with sudo -u mobile -E will solve the error for that line, only for it to reappear for on a later line or in another file. Since I am running the build scripts as mobile, I do not understand how this could possibly fix the issue, yet it does. I have confirmed that making these changes does actually allow for the script to work successfully up to that point. Running the build script with sudo or sudo -u mobile -E and/or running the entire build as root does not solve the issue; with either, I still must edit build scripts to add sudo’s.
I would like to know why this is happening, and if possible how I could address the issue without editing build scripts. Any information about these types of errors would be interesting to me even if they do not solve my problem. I am aware that the permissions/security/entitlements system is unusual on iOS and would like to learn more about how it works.
I am using an iPad Pro 4 on jailbroken iOS 13.5 with the build tools from sbingner’s and MCApollo’s repos (repo.bingner.com and mcapollo.github.io/Public). In particular, I am using a build of LLVM 5 (manually installed from sbingner’s old debs), Clang 10, Darwin CC tools 927 and GNU Make 4.2.1. I have set CC, CXX, CFLAGS, etc. to point to clang-10 and my iOS 13.5 SDK with -isysroot and have confirmed that these settings are working. I would like to replace these with updated versions, but I cannot yet build these tools for myself due to this issue and a few others. I do have access to a Mac for cross-compilation if necessary, but I would rather use only my iPad because I like the challenge.
I can attach any logs necessary or provide more information if that would be useful; I do not know enough about this issue to know what information is useful. Thanks in advance for helping me!
For anyone who ends up needing to address this issue on a jailbreak that does not have a fix for this issue, I have written (pasted below) a userland hook based on the posix_spawn implementation from the source of Apple’s xnu kernel.
Compile it with Theos, and inject it into all processes spawned by your shell by setting environment variable DYLD_INSERT_LIBRARIES to the path of the resulting dylib. Note: some tweak injectors (namely libhooker, see here) reset DYLD_INSERT_LIBRARIES, so if you notice this behavior, be sure to inject only your library.
Because the implementation of the exec syscalls in iOS call out to posix_spawn, this hook fixes all of the exec-related issue’s I’ve run into so far.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <spawn.h>
// Copied from bsd/kern/kern_exec.c
#define IS_WHITESPACE(ch) ((ch == ' ') || (ch == '\t'))
#define IS_EOL(ch) ((ch == '#') || (ch == '\n'))
// Copied from bsd/sys/imgact.h
#define IMG_SHSIZE 512
// Here, we provide an alternate implementation of posix_spawn which correctly handles #!.
// This is based on the implementation of posix_spawn in bsd/kern/kern_exec.c from Apple's xnu source.
// Thus, I am fairly confident that this posix_spawn has correct behavior relative to macOS.
%hookf(int, posix_spawn, pid_t *pid, const char *orig_path, const posix_spawn_file_actions_t *file_actions, const posix_spawnattr_t *attrp, char *const orig_argv[], char *const envp[]) {
// Call orig before checking for anything.
// This mirrors the standard implementation of posix_spawn because it first checks if we are spawning a binary.
int err = %orig;
// %orig returns EPERM when spawning a script.
// Thus, if err is anything other than EPERM, we can just return like normal.
if (err != EPERM)
return err;
// At this point, we do not need to check for exec permissions or anything like that.
// because posix_spawn would have returned that error instead of EPERM.
// Now we open the file for reading so that we can check if it's a script.
// If it turns out not to be a script, the EPERM must be from something else
// so we just return err.
FILE *file = fopen(orig_path, "r");
if (file == NULL) {
return err;
}
if (fseek(file, 0, SEEK_SET)) {
return err;
}
// In exec_activate_image, the data buffer is filled with the first PAGE_SIZE bytes of the file.
// However, in exec_shell_imgact, only the first IMG_SHSIZE bytes are used.
// Thus, we read IMG_SHSIZE bytes out of our file.
// The buffer is filled with newlines so that if the file is not IMG_SHSIZE bytes,
// the logic reads an IS_EOL.
char vdata[IMG_SHSIZE] = {'\n'};
if (fread(vdata, 1, IMG_SHSIZE, file) < 2) { // If we couldn't read at least two bytes, it's not a script.
fclose(file);
return err;
}
// Now that we've filled the buffer, we don't need the file anymore.
fclose(file);
// Now we follow exec_shell_imgact.
// The point of this is to confirm we have a script
// and extract the usable part of the interpreter+arg string.
// Where they return -1, we don't have a shell script, so we return err.
// Where they return an error, we return that same error.
// We don't bother doing any SUID stuff because SUID scripts should be disabled anyway.
char *ihp;
char *line_startp, *line_endp;
// Make sure we have a shell script.
if (vdata[0] != '#' || vdata[1] != '!') {
return err;
}
// Try to find the first non-whitespace character
for (ihp = &vdata[2]; ihp < &vdata[IMG_SHSIZE]; ihp++) {
if (IS_EOL(*ihp)) {
// Did not find interpreter, "#!\n"
return ENOEXEC;
} else if (IS_WHITESPACE(*ihp)) {
// Whitespace, like "#! /bin/sh\n", keep going.
} else {
// Found start of interpreter
break;
}
}
if (ihp == &vdata[IMG_SHSIZE]) {
// All whitespace, like "#! "
return ENOEXEC;
}
line_startp = ihp;
// Try to find the end of the interpreter+args string
for (; ihp < &vdata[IMG_SHSIZE]; ihp++) {
if (IS_EOL(*ihp)) {
// Got it
break;
} else {
// Still part of interpreter or args
}
}
if (ihp == &vdata[IMG_SHSIZE]) {
// A long line, like "#! blah blah blah" without end
return ENOEXEC;
}
// Backtrack until we find the last non-whitespace
while (IS_EOL(*ihp) || IS_WHITESPACE(*ihp)) {
ihp--;
}
// The character after the last non-whitespace is our logical end of line
line_endp = ihp + 1;
/*
* Now we have pointers to the usable part of:
*
* "#! /usr/bin/int first second third \n"
* ^ line_startp ^ line_endp
*/
// Now, exec_shell_imgact copies the interpreter into another buffer and then null-terminates it.
// Then, it copies the entire interpreter+args into another buffer and null-terminates it for later processing into argv.
// This processing is done in exec_extract_strings, which goes through and null-terminates each argument.
// We will just do this all at once since that's much easier.
// Keep track of how many arguments we have.
int i_argc = 0;
ihp = line_startp;
while (true) {
// ihp is on the start of an argument.
i_argc++;
// Scan to the end of the argument.
for (; ihp < line_endp; ihp++) {
if (IS_WHITESPACE(*ihp)) {
// Found the end of the argument
break;
} else {
// Keep going
}
}
// Null terminate the argument
*ihp = '\0';
// Scan to the beginning of the next argument.
for (; ihp < line_endp; ihp++) {
if (!IS_WHITESPACE(*ihp)) {
// Found the next argument
break;
} else {
// Keep going
}
}
if (ihp == line_endp) {
// We've reached the end of the arg string
break;
}
// If we are here, ihp is the start of an argument.
}
// Now line_startp is a bunch of null-terminated arguments possibly padded by whitespace.
// i_argc is now the count of the interpreter arguments.
// Our new argv should look like i_argv[0], i_argv[1], i_argv[2], ..., orig_path, orig_argv[1], orig_argv[2], ..., NULL
// where i_argv is the arguments to be extracted from line_startp;
// To allocate our new argv, we need to know orig_argc.
int orig_argc = 0;
while (orig_argv[orig_argc] != NULL) {
orig_argc++;
}
// We need space for i_argc + 1 + (orig_argc - 1) + 1 char*'s
char *argv[i_argc + orig_argc + 1];
// Copy i_argv into argv
int i = 0;
ihp = line_startp;
for (; i < i_argc; i++) {
// ihp is on the start of an argument
argv[i] = ihp;
// Scan to the next null-terminator
for (; ihp < line_endp; ihp++) {
if (*ihp == '\0') {
// Found it
break;
} else {
// Keep going
}
}
// Go to the next character
ihp++;
// Then scan to the next argument.
// There must be another argument because we already counted i_argc.
for (; ihp < line_endp; ihp++) {
if (!IS_WHITESPACE(*ihp)) {
// Found it
break;
} else {
// Keep going
}
}
// ihp is on the start of an argument.
}
// Then, copy orig_path into into argv.
// We need to make a copy of orig_path to avoid issues with const.
char orig_path_copy[strlen(orig_path)+1];
strcpy(orig_path_copy, orig_path);
argv[i] = orig_path_copy;
i++;
// Now, copy orig_argv[1...] into argv.
for (int j = 1; j < orig_argc; i++, j++) {
argv[i] = orig_argv[j];
}
// Finally, add the null.
argv[i] = NULL;
// Now, our argv is setup correctly.
// Now, we can call out to posix_spawn again.
// The interpeter is in argv[0], so we use that for the path.
return %orig(pid, argv[0], file_actions, attrp, argv, envp);
}

iOS Mach-O – Make __TEXT segment temporarily writable

I've tried a lot to finally get this working, but it still doesn't work yet.
Im trying to change some variables in the __TEXT section, which is read-only by default, like changing the cryptid (and other stuff)
It kind of worked a while ago, back on 32 bit devices. But somehow, it always fails after I used the 64bit commands.
It currently crashes if I hit the following lines:
tseg->maxprot = tseg->initprot = VM_PROT_READ | VM_PROT_EXECUTE
or
crypt->cryptid = 1.
struct mach_header_64* mach = (struct mach_header_64*) _dyld_get_image_header(0);
uint64_t header_size = 0;
struct encryption_info_command_64 *crypt;
struct segment_command_64 *tseg;
struct dylib_command *protector_cmd;
// clean up some commands
void *curloc = (void *)mach + sizeof(struct mach_header);
for (int i=0;i<mach->ncmds;i++) {
struct load_command *lcmd = curloc;
if (lcmd->cmd == LC_ENCRYPTION_INFO_64) {
// save crypt cmd
crypt = curloc;
} else if (lcmd->cmd == LC_SEGMENT_64) {
struct segment_command_64 *seg = curloc;
if (seg->fileoff == 0 && seg->filesize != 0) {
header_size = seg->vmsize;
tseg = curloc;
}
}
if(i == mach->ncmds-1){
protector_cmd = curloc;
}
curloc += lcmd->cmdsize;
}
kern_return_t err;
// make __TEXT temporarily writable
err = vm_protect(mach_task_self(), (vm_address_t)mach, (vm_size_t)header_size, false, VM_PROT_ALL);
if (err != KERN_SUCCESS) exit(1);
// modify the load commands
// change protection of __TEXT segment
tseg->maxprot = tseg->initprot = VM_PROT_READ | VM_PROT_EXECUTE;
// change cryptid
crypt->cryptid = 1;
There's no point in changing the load command. The load commands were already processed when the program was loaded (which must be before this code of yours can run). They have no further effect on the protection of pages.
You're apparently already aware of the vm_protect() function. So why aren't you using that to make the text segment itself writable rather than trying to make the load commands writable?
And it's surely simpler to use getsegmentdata() to locate the segment in memory than looking at the load commands (to which you'd have to add the slide).
Beyond that, I would be surprised if iOS lets you do that. There's a general prohibition against run-time modifiable code (with very narrow exceptions).

h264 error while decoding

I wanna get frames from my ip camera but same errors occured. I read some web page about that error but i couldnt solve the problem. I am using visual C++ 2010
Code :
cv::VideoCapture capture("rtsp://192.168.0.18:554/ucast/11");
if (!capture.isOpened()) return 1;
double width = capture.get(CV_CAP_PROP_FRAME_WIDTH);
double height = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
cv::namedWindow("showRTSP", CV_WINDOW_AUTOSIZE);
while (true) {
cv::Mat frame;
if (!capture.read(frame)) break;
cv::imshow("showRTSP", frame);
if (cv::waitKey(30) == 27) break;
}
Errors : [h264 # 00000000030afaa0] error while decoding MB 59 10
thanks...

iOS - Issue recieving data from NSStream

I am making an application that senses iBeacons. When you get within immediate range of an iBeacon the application sends the major and minor numbers of the beacon to a server and the server sends back an image that is stored in a MySQL database, different images are sent back based on the major and minor numbers.
The application sends the major and minor number to a Python (Twisted sockets) script via an NSStream, the script uses these numbers to get an image from the database and send it back to the application.
This setup work great when I use it to get simple text messages back from the database but I am running into problems when trying to recieve and display images inside the application.
first I will post the code of the stream:handleEvent that recieves the data from the input stream.
The code is only a slight modification of this tutorial http://www.raywenderlich.com/3932/networking-tutorial-for-ios-how-to-create-a-socket-based-iphone-app-and-server
// input stream event that recieves the data from the server
//
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode)
{
case NSStreamEventOpenCompleted:
NSLog(#"stream opened");
break;
case NSStreamEventHasBytesAvailable: // event for recieving data
NSLog(#"Recieved Data");
if (aStream == _inputStream)
{
uint8_t buffer[500000];
int len;
// loop gets bytes from input stream
//
while ([_inputStream hasBytesAvailable])
{
len = [_inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
NSString *str = #"data:image/jpg;base64,";
NSString *img = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
str = [str stringByAppendingString:img];
NSData *ImgOut = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];
if (nil != ImgOut)
{
self.ImageView.image = [UIImage imageWithData:ImgOut];
NSLog(#"show image");
}
}
}
}
break;
case NSStreamEventErrorOccurred:
NSLog(#"can not connect to host");
[self initNetworkComms];
break;
case NSStreamEventEndEncountered:
NSLog(#"Connection Lost");
[_outputStream close];
[_inputStream close];
[self initNetworkComms];
break;
default:
NSLog(#"unkown event");
break;
}
}
just for good measure I will post the code of the Python script
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
import mysql.connector
db = mysql.connector.connect(user='NotImportant', password='WouldntYouLikeToKnow', host='localhost', database='retailbeacons')
cursor = db.cursor()
class MessageServer(Protocol):
def connectionMade(self):
self.factory.clients.append(self)
print "clients are ", self.factory.clients
def connectionLost(self, reason):
self.factory.clients.remove(self)
print "client has disconnected"
def dataReceived(self, data):
a = data.split(':')
if len(a) > 1:
Major = a[0]
Minor = a[1]
msg = ""
print "Received query " + Major + ":" + Minor
sql = "SELECT Picture FROM beaconinfo WHERE major=" + Major + " AND minor=" + Minor + ";"
cursor.execute(sql)
for row in cursor.fetchall():
mess = row[0]
msg = mess.encode('utf=8')
self.message(msg)
def message(self, message):
self.transport.write(message + '\n')
factory = Factory()
factory.protocol = MessageServer
factory.clients = []
reactor.listenTCP(8080, factory)
print "Python message test server started"
reactor.run()
what happens with this code is that when the app queries the server, the server sends back the image data (in base64 format), the application recieves this data and the EventHasBytesAvailable case of the switch statement is triggered. But only a small portion of the image is displayed and I get an error log saying:
<Error>: ImageIO: JPEG Corrupt JPEG data: premature end of data segment
This led me to believe that not all the data came across the stream. you'll see in the code that I have an NSLog say 'Recieved Data' everytime the EventHasBytesAvailable case is called and 'show image' when the UIImageView is set with the image data.
The thing I find odd, and what I feel is the source of this problem is the fact that when the EventHasBytesAvailable is called the 'Recieved Data' message is logged, then the 'show image' message is logged, then once again the 'Recieved Data' message is logged and the Error listed above is then logged.
So it looks like a small portion of the data comes in through the stream, the loop gathers up those bytes and sticks them in the UIImageView, then more bytes come in through the stream and an attempt to put them into the UIImageView is made but the 'premature end of data segment' error occurs.
I am very confused as to why this is happening. Shouldn't the whole data of the image be sent through the stream with one calling of the EventHasBytesAvailable case? Possibly I have over looked the buffer in my code? Can my buffer take an image of 60kb? That is the only thing I can think of that might be wring with the application code, then all i can think of is maybe the Python script is sending the data in two chunks instead of one.
Thank you for your time. I am an intern that has hit a bit of a wall with this one! any help will be greatly appreciated!
fixed this problem. so the stream was sending the data over in more than one call of the 'HasBytes' case. so i created a string that gets appended with each chunk of the data when 'HasBytes' gets called. i also used a different method for converting the image data string to an NSData object.
NSString *ImgStr = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
// string property for appending
//
_str = [_str stringByAppendingString:ImgStr];
NSData *ImgData = [[NSData alloc] initWithBase64EncodedString:_str options:1];
if (nil != ImgData)
{
self.ImageView.image = [UIImage imageWithData:ImgData];
}
Thanks very much!

Javascript minification logic where immutable properties are involved

A question on the minifying logic.
// Assumptions:
//com.example.dummy ns is available
//com.example.dummy.type is defined immutable -> Object.defineProperty
var test, test1, test2;
function execute_case(id) {
switch(id) {
case 0:
test = com.example.dummy.type;
break;
case 1:
test1 = com.example.dummy.type;
break;
case 2:
test2 = com.example.dummy.type;
break;
default:
console.log("default");
break;
}
}
the YUI compressor compresses it to,
var test,test1,test2;function execute_case(a){switch(a){case 0:
test=com.example.dummy.type;break;case 1:test1=com.example.dummy.type;break;
case 2:test2=com.example.dummy.type;break;default:console.log("default");break}};
Wouldn't it be logical for the compressor do the following as an optimization?
var test, test1, test2;
var st = com.example.dummy.type;
function execute_case(id) {
switch(id) {
case 0:
test = st;
case 1:
test1 = st;
break;
case 2:
test2 = st;
break;
default:
console.log("default");
break;
}
}
As can be seen, the compression here works out better.
var test,test1,test2;var st=com.example.dummy.type;function execute_case(a){
switch(a){case 0:test=st;case 1:test1=st;break;case 2:test2=st;break;
default:console.log("default");break}};
That optimization makes sense for uncompressed source code, but not if the file is delivered with gzip compression (which is highly recommended).
String aliasing tends to make the compressed source code larger.
See the Closure-compiler FAQ

Resources