Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can PHP return a Resource with ID# 0?

Tags:

php

resources

I'm wondering if it's possible for a valid PHP Resource to have an ID of 0. I am getting database connection resources and so far they have all been non-zero positive integers. Just curious what the range of potential IDs is for resources.

like image 970
aw crud Avatar asked Aug 04 '11 15:08

aw crud


2 Answers

The resource id may be in the range of an int. Search for "resource" or "ZEND_FETCH_RESOURCE" in the source code directory of PHP via the terminal. Then you'll see the function:
(file ./Zend/zend_list.c, line 110)

ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id,
char *resource_type_name, int *found_resource_type, int num_resource_types, ...)

Inside the function, you'll see that passed_id is the resource's id and it's of type int.
Normally, libraries pass a default id of -1, for example in file ./ext/mysql/php_mysql.c, line 1060.

In general you can assume that all the libraries will pass a real/exists resource id with value greater than 0, but that's not a rule that every library must follow - it is possible to pass a negative resource id or 0.

like image 150
Dor Avatar answered Oct 27 '22 16:10

Dor


It seems not... I couldn't find exactly why, but here's what I've tried (perhaps someone else can shed some more light about this behaviour for the zend engine)

1.- In C, I wrote a very silly program that generates a file descriptor #0 (this is not analogous to a resource in php, but I've tried this with file resources just so we can somehow relate both languages)

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int
main(int argc, char *argv[])
{
    int a;
    char buff[8];
    close(0);
    close(1);
    close(2);
    a = open("./output", O_CREAT | O_TRUNC | O_WRONLY);
    sprintf(buff, "%d\n", a);
    write(a, buff, strlen(buff));
    close(a);
}

This code will close file descriptors 0, 1, 2. open a new file and save the descriptor, which results:

$ cat output

0

$

now, in php:

<?php
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);

$asd = fopen('./outputphp', 'w');
fwrite($asd, print_r($asd, true));
fclose($asd);

this will output:

$ cat outputphp

Resource id #5

$

so even closing stdin, stdout, and stderr, php will not reuse resource id's. even more, stdin id #1, stdout is #2 and stderr is #3 when in fact stdin has file descriptor 0, stdout has 1, and stderr has 2. also, there is another id #4 already allocated.

so I'd say that php reserves the id #0 or wont use it at all.

greping through the zend engine code, i found that actually the resource #0 is used across all code that initializes the zend engine in either sapi (cgi, cli, modules, etc) when ZTS (thread safety is enabled). like:

tsrm_startup(1, 1, 0, NULL);
tsrm_ls = ts_resource(0);

when cleaning up the zend engine, it will traverse the resource table starting from the id #0. You cant (at least I couldnt) get a resource #0 with or without thread safety enabled, so #0 seems to be reserved for both cases but used only when ts enabled.

EDIT: to sum up ;) seems that you cant have a resource id less than 1, being 1, 2, 3 opened by default (not sure about the #4, but its possible that any new resources you will open will start at #4 or #5)

like image 35
marcelog Avatar answered Oct 27 '22 14:10

marcelog