ID: 3697
Updated by: [EMAIL PROTECTED]
Reported By: [EMAIL PROTECTED]
-Status: Analyzed
+Status: Closed
Bug Type: Feature/Change Request
Operating System: BSD/OS 4.0.1
PHP Version: 4.0 Beta 4 Patch Level 1
New Comment:
seems to be fixed.
Previous Comments:
------------------------------------------------------------------------
[2000-08-01 01:01:08] [EMAIL PROTECTED]
DJM reports that problem is fixed. However, he suggests that there is a
better solution to the problem than was implemented. See message
below.
"I just checked the CVS version. The primary bug I reported is fixed
in the current sources, though in a somewhat less robust (but simpler)
way than I suggested. I would still like to have more warning messages
instead of silent failures in various exceptional conditions, as
suggested in my patch; that has not been done so far. Also, spurious
whitespace has been added in a comment in main/php_realpath.c:260:
/* C heck for overflow */
"
------------------------------------------------------------------------
[2000-07-29 23:59:54] [EMAIL PROTECTED]
Have you tried a recent release? If so, does the problem still occur?
------------------------------------------------------------------------
[2000-03-02 01:24:46] [EMAIL PROTECTED]
Some more warning messages to alert about exceptional conditions would
be helpful. Also, there's a misformatted warning message due to the
appending of " in <script>...".
And, there's a place in the distributed code that's missing the
PHP_WIN32 case.
So here's my final (I think) suggested patch:
Index: fopen-wrappers.c
===================================================================
retrieving revision 1.2
diff -u -r1.2 fopen-wrappers.c
--- fopen-wrappers.c 2000/03/01 04:32:29 1.2
+++ fopen-wrappers.c 2000/03/02 06:14:53
@@ -120,21 +120,26 @@
}
/* Resolve the real path into resolved_name */
- if ((php_realpath(path, resolved_name) != NULL) &&
(php_realpath(local_open_basedir, resolved_basedir) != NULL)) {
+ if (php_realpath(path, resolved_name) == NULL) {
+ /* Unable to resolve the real path, return -1 */
+ return -1;
+ } else if (php_realpath(local_open_basedir, resolved_basedir)
== NULL) {
+ /* Unable to resolve the real path, return -1 */
+ php_error(E_WARNING, "cannot resolve open_basedir %s",
local_open_basedir);
+ return -1;
+ } else {
/* Check the path */
#ifdef PHP_WIN32
- if (strncasecmp(resolved_basedir, resolved_name,
strlen(resolved_basedir)) == 0) {
+ if (strncasecmp(resolved_basedir, resolved_name,
strlen(resolved_basedir)) == 0)
#else
- if (strncmp(resolved_basedir, resolved_name,
strlen(resolved_basedir)) == 0) {
+ if (strncmp(resolved_basedir, resolved_name,
strlen(resolved_basedir)) == 0)
#endif
+ {
/* File is in the right directory */
return 0;
} else {
return -1;
}
- } else {
- /* Unable to resolve the real path, return -1 */
- return -1;
}
}
@@ -170,7 +175,7 @@
ptr = end;
}
- php_error(E_WARNING, "open_basedir restriction in
effect. File is in wrong directory.");
+ php_error(E_WARNING, "open_basedir restriction in
effect. File is in wrong directory");
efree(pathbuf);
return -1;
}
Index: php_realpath.c
===================================================================
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 php_realpath.c
--- php_realpath.c 2000/03/01 04:23:33 1.1.1.1
+++ php_realpath.c 2000/03/02 06:20:56
@@ -97,6 +97,7 @@
if (getcwd(path_construction, MAXPATHLEN-1) == NULL) {
/* Unable to get cwd */
resolved_path[0] = 0;
+ php_error(E_WARNING, "cannot get current
directory");
return NULL;
}
strcat(path_construction, "/");
@@ -213,7 +214,10 @@
/* Check the current location to see if it is a symlink
*/
if((linklength = readlink(path_construction, buf,
MAXPATHLEN)) != -1) {
/* Check linkcount */
- if (linkcount > MAXSYMLINKS) return NULL;
+ if (linkcount > MAXSYMLINKS) {
+ php_error(E_WARNING, "detected symlink
loop in %s", path);
+ return NULL;
+ }
/* Count this symlink */
linkcount++;
@@ -222,7 +226,10 @@
buf[linklength] = 0;
/* Check for overflow */
- if ((strlen(workpos) + strlen(buf) + 1) >=
MAXPATHLEN) return NULL;
+ if ((strlen(workpos) + strlen(buf) + 1) >=
MAXPATHLEN) {
+ php_error(E_WARNING, "overflow in %s",
path);
+ return NULL;
+ }
/* Remove the symlink-component wrom
path_construction */
writepos--;
/* move to '/' */
@@ -251,12 +258,31 @@
}
/* Check if the resolved path is a directory */
- if (stat(path_construction, &filestat) != 0) return NULL;
+ if (stat(path_construction, &filestat) != 0) {
+ /* It doesn't exist yet; check the directory it's in
instead. */
+#ifdef PHP_WIN32
+ while (*--writepos != '\\' && writepos >
path_construction)
+#else
+ while (*--writepos != '/' && writepos >
path_construction)
+#endif
+ ;
+ *writepos = 0;
+ if (stat(path_construction, &filestat) != 0) {
+ return NULL;
+ }
+ }
if (S_ISDIR(filestat.st_mode)) {
/* It's a directory, append a / if needed */
+#ifdef PHP_WIN32
+ if (*(writepos-1) != '\\') {
+#else
if (*(writepos-1) != '/') {
+#endif
/* Check for overflow */
- if ((strlen(workpos) + 2) >= MAXPATHLEN) return
NULL;
+ if ((strlen(workpos) + 2) >= MAXPATHLEN) {
+ php_error(E_WARNING, "overflow in %s",
path);
+ return NULL;
+ }
*writepos++ = '/';
*writepos = 0;
------------------------------------------------------------------------
[2000-03-02 01:05:37] [EMAIL PROTECTED]
I should mention that an appropriate #ifdef PHP_WIN32 case would also
have to be added. Actually, the win32 support could be more cleanly
implemented by doing
#ifdef PHP_WIN32
#define DIRSEP '\\'
#else
#define DIRSEP '/'
#endif
instead of duplicating a lot of while loops and ifs.
------------------------------------------------------------------------
[2000-03-02 00:57:16] [EMAIL PROTECTED]
I have open_basedir set and I am trying to create a file under that
directory using
$fp = fopen("cities.wddx", "w");
However, it fails:
<b>Warning</b>: open_basedir restriction in effect. File is in wrong
directory in <b>/homes/web/testtest5/html/serialize.php</b> on line
<b>17</b><br>
Adding some more warning messages to the PHP source code reveals that
the stat() toward the end of php_realpath() is the culprit. Of course
it can't stat the file if I'm trying to create it. A suggested fix:
Index: php_realpath.c
@@ -251,12 +258,25 @@
}
/* Check if the resolved path is a directory */
- if (stat(path_construction, &filestat) != 0) return NULL;
+ if (stat(path_construction, &filestat) != 0) {
+ /* It doesn't exist yet; check the directory it's in
instead. */
+ while (*--writepos != '/' && writepos >
path_construction)
+ ;
+ *writepos = 0;
+ if (stat(path_construction, &filestat) != 0) {
+ return NULL;
+ }
+ }
if (S_ISDIR(filestat.st_mode)) {
/* It's a directory, append a / if needed */
if (*(writepos-1) != '/') {
/* Check for overflow */
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=3697&edit=1