PHP Extension return structure - structure

I am working on a PHP extension and wants to let PHP returns a structure. But it always cause core dump. My step is:
./ext_skel --extname=test
./configure --enable-test
in php_test.h, add:
typedef struct mydata {
int m_id;
int m_age;
}MYDATA;
PHP_FUNCTION(wrap_getMydata);`
In test.c, add:
#define MY_RES_NAME "my_resource";
static int my_resource_descriptor;
PHP_FE(wrap_getMydata, NULL)
...
ZEND_MINIT_FUNCTION(test)
{
/* If you have INI entries, uncomment these lines
REGISTER_INI_ENTRIES();
*/
resid = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);
return SUCCESS;
}
PHP_FUNCTION(test_getMydata)
{
zval* res;
long int a, b;
long int result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
return;
}
MYDATA objData;
objData.m_id = a;
objData.m_age = b;
ZEND_REGISTER_RESOURCE(res, &objData, resid);
RETURN_RESOURCE(res);
}
add: var_dump(test_getMydata(3,4)) in test.php
then make; make install; ./php test.php, it prints:
Functions available in the test extension:
confirm_wrap_compiled
test_getMydata
Congratulations! You have successfully modified ext/wrap/config.m4. Module wrap is now compiled into PHP.
Segmentation fault (core dumped)
$ gdb ../../bin/php core.23310
Loaded symbols for /home/user1/php/php-5.2.17/lib/php/extensions/no-debug-non-zts-20060613/test.so
#0 0x00000000006388ad in execute (op_array=0x2a9569bd68) at /home/user1/php/php-5.2.17/Zend/zend_vm_execute.h:92
92 if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0) {`
Can someone give some help?

sorry for the bad formatting in the comment - here is my final answer:
i had to rename the extension from test enter code hereto hjtest - everthing else should be pretty much in line with your posted sample.
tl;dr - the problem - and SIGSEGV in your sample is that you are registering a resource to a local variable objData - wich at the end of the function is not reachable anymore - you need to use emalloc to get a piece of dynamic memory - wich holds your MYDATA
as from there you have a resource - bound to some piece of dyn. memory, you need to register a dtor function - so you can release/efree your registered memory.
hope that helps.
to solve the above issue - modifie your resource registration like this:
MYDATA * objData=emalloc(sizeof(MYDATA));
objData->m_id = a;
objData->m_age = b;
ZEND_REGISTER_RESOURCE(return_value, objData, resid);
and add a dtor:
... MINIT
resid = zend_register_list_destructors_ex(resdtor, NULL, MY_RES_NAME, module_number);
and
static void resdtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
MYDATA *res = (MYDATA*)rsrc->ptr;
if (res) {
efree(res);
}
}
for full sample see this GIST: https://gist.github.com/hjanuschka/3ed54e66f017a379cf25

Related

Unable to open file after FUSE mount

I'm trying out FUSE for the first time by following the official GitHub Repo's example.
I have done the following:
created a mount directory called mount_dir that contains file hello.txt.
update /etc/fuse.conf with user_allow_other as mentioned in various forums and posts
Added bunch of printf() statements in hello_ll.c at all function entry points.
Executed ./hello_ll -o allow_other -f /home/hemalkumar/mount_dir
Executed ./test_stat. It calculate the number of pages in the file. Just some business logic, nothing fancy!
test_stat.c
#define PAGE_SIZE 4096
int main() {
char* filename = "/home/hemalkumar/mount_dir/hello.txt";
int fd = open(filename, O_RDONLY);
if (fd == -1) {
printf("INVALID file:%s\n", filename);
close(fd);
return -1;
}
struct stat sb;
if (fstat(fd, &sb) == -1) {
close(fd);
return -1;
}
int pages = sb.st_size/PAGE_SIZE + (sb.st_size % PAGE_SIZE != 0);
printf("pages:%d\n", pages);
return 0;
}
Issue:
When I execute test_stat without mounting FUSE, it works fine. However, running it after step#4 shows an error INVALID file:/home/hemalkumar/mount_dir/hello.txt.
I have updated /etc/fuse.conf file to allow other user, and passing flags during startup of hello_ll. Don't know what permission issues it is having.
Any pointers will be appreciated!
Thanks!

ASSERT_THROW: error: void value not ignored as it ought to be

I am beginner to gtest. I trying to use ASSERT_THROW will compilation fail. Could anyone help on this:
class my_exp {};
int main(int argc, char *argv[])
{
EXPECT_THROW(throw my_exp(), my_exp); // this will pass
// This will through below compilation error
ASSERT_THROW(throw my_exp(), my_exp);
return 0;
}
Compilation output:
ERROR :
In file included from /usr/include/gtest/gtest.h:57:0,
from gtest.cpp:1:
gtest.cpp: In function ‘int main(int, char**)’:
gtest.cpp:12:3: error: void value not ignored as it ought to be
ASSERT_THROW(throw my_exp(), my_exp);
^
Short version
You write test in the wrong way, to write test you should put assertion inside test (macro TEST) or test fixtures (macro TEST_F).
Long version
1 . What's really happens?
To find out the real problem is not easy because the Google Testing Framework use macros which hide real code. To see code after macro substitution is required to perform preprocessing, something like this:
g++ -E main.cpp -o main.p
The result of preprocessing when using ASSERT_THROW will be looks like this (after formatting):
class my_exp {};
int main(int argc, char *argv[])
{
switch (0)
case 0:
default:
if (::testing::internal::ConstCharPtr gtest_msg = "") {
bool gtest_caught_expected = false;
try {
if (::testing::internal::AlwaysTrue () ) {
throw my_exp ();
};
} catch (my_exp const &) {
gtest_caught_expected = true;
} catch (...) {
gtest_msg.value = "Expected: throw my_exp() throws an exception of type my_exp.\n Actual: it throws a different type.";
goto gtest_label_testthrow_7;
} if (!gtest_caught_expected) {
gtest_msg.value = "Expected: throw my_exp() throws an exception of type my_exp.\n Actual: it throws nothing.";
goto gtest_label_testthrow_7;
}
}
else
gtest_label_testthrow_7:
return ::testing::internal::AssertHelper (::testing::TestPartResult::kFatalFailure, "main.cpp", 7, gtest_msg.value) = ::testing::Message ();
return 0;
}
For EXPECT_THROW result will be the same except some difference:
else
gtest_label_testthrow_7:
::testing::internal::AssertHelper (::testing::TestPartResult::kNonFatalFailure, "main.cpp", 7, gtest_msg.value) = ::testing::Message ();
2 . OK, the reason of different behaviour is found, let's continue.
In the file src/gtest.cc can be found AssertHelper class declaration including assignment operator which return void:
void AssertHelper::operator=(const Message& message) const
So now reason of the compiler complain is clarified.
3 . But why this problem is caused is not clear. Try realise why for ASSERT_THROW and EXPECT_THROW different code was generated. The answer is the macro from file include/gtest/internal/gtest-internal.h
#define GTEST_FATAL_FAILURE_(message) \
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
#define GTEST_NONFATAL_FAILURE_(message) \
GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
which contain return for fatal case.
4 . But now is question why this assertions usually works well?
To answer of this question try investigate code snipped which written in correct way when assertion is placed inside test:
#include <gtest/gtest.h>
class my_exp {};
TEST (MyExp, ThrowMyExp)
{
ASSERT_THROW (throw my_exp (), my_exp);
}
To exclude pollution of the answer I just notice that in such case the return statement for ASSERT_THROW also exist, but it is placed inside method:
void MyExp_ThrowMyExp_Test::TestBody ()
which return void! But in your example assertions are placed inside main function which return int. Looks like this is source of problem!
Try prove this point with simple snippet:
void f1 () {};
void f2 () {return f1();};
//int f2 () {return f1();}; // error here!
int main (int argc, char * argv [])
{
f2;
return 0;
}
5 . So the final answer is: the ASSERT_THROW macro contain return statement for expression which evaluates to void and when such expression is placed into function which return non void value the gcc complain about error.
P.S. But anyway I have no idea why for one case return is used but for other case is not.
Update: I've asked this question on GitHub and got the following answer:
ASSERT_XXX is used as a poor man's exception to allow it to work in
environments where exceptions are disabled. It does a return; instead.
It is meant to be used from within the TEST() methods, which return
void.
Update: I've just realised that this question described in the official documentation:
By placing it in a non-void function you'll get a confusing compile error > like "error: void value not ignored as it ought to be".

return of a local variable by ref works

Take a look at this C++ code:
#include <iostream>
using namespace std;
class B{
public:
int& f() {
int local_n = 447;
return local_n ;
} // local_n gets out of scope here
};
int main()
{
B b;
int n = b.f(); // and now n = 447
}
I don't understand why n = 447 at the end of main, because I tried to return a reference to a local_n, when it should be NULL;
Returning a reference to a local variable invokes undefined behavior - meaning you might get lucky and it might work... sometimes... or it might format your hard drive or summon nasal demons. In this case, the compiler generated code that managed to copy the old value off the stack before it got overwritten with something else. Oh, and references do not have a corresponding NULL value...
Edit - here's an example where returning a reference is a bad thing. In your example above, since you copy the value out of the reference immediately before calling anything else, it's quite possible (but far from guaranteed) that it might work most of the time. However, if you bind another reference to the returned reference, things won't look so good:
extern void call_some_other_functions();
extern void lucky();
extern void oops();
int& foo()
{ int bar = 0;
return bar;
}
main()
{ int& x = foo();
x = 5;
call_some_other_functions();
if (x == 5)
lucky();
else
oops();
}

transform javascript to opcode using spidermonkey

i am new to spider monkey and want to use it for transform java script file to sequence of byte code.
i get spider monkey and build it in debug mode.
i want to use JS_CompileScript function in jsapi.h to compile javascript code and analysis this to get bytecode , but when in compile below code and run it , i get run time error.
the error is "Unhandled exception at 0x0f55c020 (mozjs185-1.0.dll) in spiderMonkeyTest.exe: 0xC0000005: Access violation reading location 0x00000d4c." and i do not resolve it.
any body can help me to resolve this or introducing other solutions to get byte code from javascript code by using spider monkey ?
// spiderMonkeyTest.cpp : Defines the entry point for the console application.
//
#define XP_WIN
#include <iostream>
#include <fstream>
#include "stdafx.h"
#include "jsapi.h"
#include "jsanalyze.h"
using namespace std;
using namespace js;
static JSClass global_class = { "global",
JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub,
NULL,
JS_PropertyStub,
JS_StrictPropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL,
JSCLASS_NO_OPTIONAL_MEMBERS
};
int _tmain(int argc, _TCHAR* argv[]) {
/* Create a JS runtime. */
JSRuntime *rt = JS_NewRuntime(16L * 1024L * 1024L);
if (rt == NULL)
return 1;
/* Create a context. */
JSContext *cx = JS_NewContext(rt, 8192);
if (cx == NULL)
return 1;
JS_SetOptions(cx, JSOPTION_VAROBJFIX);
JSScript *script;
JSObject *obj;
const char *js = "function a() { var tmp; tmp = 1 + 2; temp = temp * 2; alert(tmp); return 1; }";
obj = JS_CompileScript(cx,JS_GetGlobalObject(cx),js,strlen(js),"code.js",NULL);
script = obj->getScript();
if (script == NULL)
return JS_FALSE; /* compilation error */
js::analyze::Script *sc = new js::analyze::Script();
sc->analyze(cx,script);
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
/* Shut down the JS engine. */
JS_ShutDown();
return 1;
}
Which version of Spidermonkey are you using? I am using the one that comes with FireFox 10 so the API may be different.
You should create a new global object and initialize it by calling JS_NewCompartmentAndGlobalObject() and JS_InitStandardClasses() before compiling your script :
.....
/*
* Create the global object in a new compartment.
* You always need a global object per context.
*/
global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
if (global == NULL)
return 1;
/*
* Populate the global object with the standard JavaScript
* function and object classes, such as Object, Array, Date.
*/
if (!JS_InitStandardClasses(cx, global))
return 1;
......
Note, the function JS_NewCompartmentAndGlobalObject() is obsolete now, check the latest JSAPI documentation for the version your are using. Your JS_CompileScript() call just try to retrieve a global object which has not been created and probably this causes the exception.
how about using function "SaveCompiled" ? it will save object/op-code (compiled javascript) to file

How to write a Linux Driver, that only forwards file operations?

I need to implement a Linux Kernel Driver, that (in the first step) only forwards all file operations to another file (in later steps, this should be managed and manipulated, but I don't want to discuss this here).
My idea is the following, but when reading, the kernel crashes:
static struct {
struct file *file;
char *file_name;
int open;
} file_out_data = {
.file_name = "/any_file",
.open = 0,
};
int memory_open(struct inode *inode, struct file *filp) {
PRINTK("<1>open memory module\n");
/*
* We don't want to talk to two processes at the same time
*/
if (file_out_data.open)
return -EBUSY;
/*
* Initialize the message
*/
Message_Ptr = Message;
try_module_get(THIS_MODULE);
file_out_data.file = filp_open(file_out_data.file_name, filp->f_flags, filp->f_mode); //here should be another return handling in case of fail
file_out_data.open++;
/* Success */
return 0;
}
int memory_release(struct inode *inode, struct file *filp) {
PRINTK("<1>release memory module\n");
/*
* We're now ready for our next caller
*/
file_out_data.open--;
filp_close(file_out_data.file,NULL);
module_put(THIS_MODULE);
/* Success */
return 0;
}
ssize_t memory_read(struct file *filp, char *buf,
size_t count, loff_t *f_pos) {
PRINTK("<1>read memory module \n");
ret=file_out_data.file->f_op->read(file_out_data.file,buf,count,f_pos); //corrected one, false one is to find in the history
return ret;
}
So, can anyone please tell me why?
Don't use set_fs() as there is no reason to do it.
Use file->f_fop->read() instead of the vfs_read. Take a look at the file and file_operations structures.
Why are you incrementing file_out_data.open twice and decrementing it once? This could cause you to use file_out_data.file after it has been closed.
You want to write memory in your file ou read?
Because you are reading and not writing...
possible i'm wrong