# RESOLVED: INFO: INIT_CLASS_ENTRY fails on various char entry formats

- Thread: https://externals.io/message/22356
- Original archive: https://news-web.php.net/php.internals/22356
- Started by an.dromeda@btconnect.com on 2006-03-13T02:00:57+00:00
- Messages: 2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #22356 — an.dromeda@btconnect.com — 2006-03-13T02:00:57+00:00

URL: https://externals.io/message/22356#22356

Answering my own question/observation, the following workarounds allow
use of char* name="myclass"; and overbuffered char name[100] = "myclass";
both of which fail normally since INIT_CLASS_ENTRY uses `sizeof()` not `strlen()`

// for various char* or string params
char* phpclassname = "myclass";
char phpclassname[100] = "myclass"; // or as passed in by 
string sphpname("myclass");

// deliberately ignore the name for this macro, which depends on sizeof
INIT_CLASS_ENTRY(ce, "", minicooper_class_functions); 

// set the name manually afterwards 
    // char* based
    ce.name = strdup(phpclassname);
    ce.name_length = strlen(phpclassname);

	// or

    // string based
    ce.name = strdup(sphpname.c_str());
    ce.name_length = sphpname.length();

// in fact, since ce.name = strdup() is precisely what the macro does,
// only the length needs to be appropriately set with strlen or .length()



----------  Forwarded Message  ----------

Subject: INFO: INIT_CLASS_ENTRY fails on various char entry formats
Date: Monday 13 March 2006 01:46
From: an.dromeda@btconnect.com
To: internals@lists.php.net

I was surprised to find that my class entry failed when I tried to pass the
class name as a parameter. Two common styles (char *myclassname = "myclass";
and (over-buffered) char myclassname[100] = "myclass";) both fail with
INIT_CLASS_ENTRY for a reason that becomes apparent when you look
at the source (interesting experience, having the source available!).

INIT_CLASS_ENTRY determines the classname length by sizeof(myclassname)
not strlen(myclassname), so the former char* returns 4, being the size of a
pointer, and the latter returns 100, being the size of the buffer, neither
being then intended reasonable size of the name as would have been determined
by strlen, here 7 ("myclass").

Consequently, a call to instantiate 'new myclass()' fails, with no such class
name registered.

Maybe that's 'obvious' and I should have known better, but both buffers and
static (?) strings I thought were 'reasonable' and in normal use, so I
 thought I'd flag the issue.

(Interestingly, in zend_API.c, ZEND_API int zend_disable_class(char
*class_name, uint class_name_length TSRMLS_DC) receives a char* for
class_name which it passes to INIT_CLASS_ENTRY, presumably without
ill-effect, and despite the issue above...)

Am I missing something, or is that simply a behaviour that's a) intentional,
or b) understood and just needs to be worked around.

Conundrum: I had assumed that to resolve this, I may need to set up an
'emalloc()' of the precise length required, but in fact this still does not
resolve the issue, as the char* returned by the emalloc will be `sizeof()` = 4,
whatever the string.

Is there no way therefore to pass a variable length classname to a dynamic
class creation routine? Seems a little unlikely, but I can't see it in light
of the above.

Guess I can ignore the INIT_CLASS_ENTRY macro, or let it run and then
post-assign the classname with appropriate length based on `strlen()` or
std::string.length().

Just a thought.

// Various formats tried:

  // char phpclassname[50] = "minicooper";
    // char *phpclassname = "minicooper";
    char phpclassname[11] = "minicooper"; // this works - exact + 1 for zero
    // char phpclassname[10] = "minicooper"; // this fails - insufficient
bytes (to include terminating zero)
    // char phpclassname[12] = "minicooper"; // this fails - sizeof is 'too
big' (one spare byte - buffer must be 'exact'
    // char phpclassname[50] = "minicooper"; // this fails  - ditto - too big
    // phpclassname[10] = '\0';    // this does not resolve 'too big' buffers
    // string spcname("minicooper"); // this does not work

	// Calls based on the above, as appropriate
    // INIT_CLASS_ENTRY(ce, spcname.c_str(), minicooper_class_functions);
    INIT_CLASS_ENTRY(ce, phpclassname, minicooper_class_functions);
    // INIT_CLASS_ENTRY(ce, "minicooper", minicooper_class_functions);

---

## #22364 — Marcus Boerger — 2006-03-13T09:08:04+00:00

URL: https://externals.io/message/22356#22364 · In reply to: #22356

Hello,

that's by design, we don't want to use strlen on ever execution. Instead the
macro use `sizeof()` which is done at compile time. The workaround would be to
set the string lentgh after using the macro which works pretty well.

Sidenote, you should be using 'const char* var = "string";' or even better
'const char var[] = "string";' anyway.

regards
marcus

Monday, March 13, 2006, 3:00:57 AM, you wrote:

> Answering my own question/observation, the following workarounds allow
> use of char* name="myclass"; and overbuffered char name[100] = "myclass";
> both of which fail normally since INIT_CLASS_ENTRY uses `sizeof()` not `strlen()`

> // for various char* or string params
> char* phpclassname = "myclass";
> char phpclassname[100] = "myclass"; // or as passed in by 
> string sphpname("myclass");

> // deliberately ignore the name for this macro, which depends on sizeof
> INIT_CLASS_ENTRY(ce, "", minicooper_class_functions); 

> // set the name manually afterwards 
>     // char* based
>     ce.name = strdup(phpclassname);
>     ce.name_length = strlen(phpclassname);

>         // or

>     // string based
>     ce.name = strdup(sphpname.c_str());
>     ce.name_length = sphpname.length();

> // in fact, since ce.name = strdup() is precisely what the macro does,
> // only the length needs to be appropriately set with strlen or .length()



> ----------  Forwarded Message  ----------

> Subject: INFO: INIT_CLASS_ENTRY fails on various char entry formats
> Date: Monday 13 March 2006 01:46
> From: an.dromeda@btconnect.com
> To: internals@lists.php.net

> I was surprised to find that my class entry failed when I tried to pass the
> class name as a parameter. Two common styles (char *myclassname = "myclass";
> and (over-buffered) char myclassname[100] = "myclass";) both fail with
> INIT_CLASS_ENTRY for a reason that becomes apparent when you look
> at the source (interesting experience, having the source available!).

> INIT_CLASS_ENTRY determines the classname length by sizeof(myclassname)
> not strlen(myclassname), so the former char* returns 4, being the size of a
> pointer, and the latter returns 100, being the size of the buffer, neither
> being then intended reasonable size of the name as would have been determined
> by strlen, here 7 ("myclass").

> Consequently, a call to instantiate 'new myclass()' fails, with no such class
> name registered.

> Maybe that's 'obvious' and I should have known better, but both buffers and
> static (?) strings I thought were 'reasonable' and in normal use, so I
>  thought I'd flag the issue.

> (Interestingly, in zend_API.c, ZEND_API int zend_disable_class(char
> *class_name, uint class_name_length TSRMLS_DC) receives a char* for
> class_name which it passes to INIT_CLASS_ENTRY, presumably without
> ill-effect, and despite the issue above...)

> Am I missing something, or is that simply a behaviour that's a) intentional,
> or b) understood and just needs to be worked around.

> Conundrum: I had assumed that to resolve this, I may need to set up an
> 'emalloc()' of the precise length required, but in fact this still does not
> resolve the issue, as the char* returned by the emalloc will be `sizeof()` = 4,
> whatever the string.

> Is there no way therefore to pass a variable length classname to a dynamic
> class creation routine? Seems a little unlikely, but I can't see it in light
> of the above.

> Guess I can ignore the INIT_CLASS_ENTRY macro, or let it run and then
> post-assign the classname with appropriate length based on `strlen()` or
> std::string.length().

> Just a thought.

> // Various formats tried:

>   // char phpclassname[50] = "minicooper";
>     // char *phpclassname = "minicooper";
>     char phpclassname[11] = "minicooper"; // this works - exact + 1 for zero
>     // char phpclassname[10] = "minicooper"; // this fails - insufficient
> bytes (to include terminating zero)
>     // char phpclassname[12] = "minicooper"; // this fails - sizeof is 'too
> big' (one spare byte - buffer must be 'exact'
>     // char phpclassname[50] = "minicooper"; // this fails  - ditto - too big
>     // phpclassname[10] = '\0';    // this does not resolve 'too big' buffers
>     // string spcname("minicooper"); // this does not work

>         // Calls based on the above, as appropriate
>     // INIT_CLASS_ENTRY(ce, spcname.c_str(), minicooper_class_functions);
>     INIT_CLASS_ENTRY(ce, phpclassname, minicooper_class_functions);
>     // INIT_CLASS_ENTRY(ce, "minicooper", minicooper_class_functions);

> -------------------------------------------------------




Best regards,
 Marcus
