Bug #43838 [Fbk->NoF]: variant_set with IE leads to hang
| From: | php-bugs at lists dot php dot net | Date: | Sun, 16 May 2021 04:22:08 +0000 |
| Subject: | Bug #43838 [Fbk->NoF]: variant_set with IE leads to hang | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-233842@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=43838&edit=1
ID: 43838
Updated by: php-bugs@lists.php.net
Reported by: csaba at alum dot mit dot edu
Summary: variant_set with IE leads to hang
-Status: Feedback
+Status: No Feedback
Type: Bug
Package: COM related
Operating System: Win XP Pro
PHP Version: 5.2.5
Assigned To: cmb
Private report: N
New Comment:
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
Previous Comments:
------------------------------------------------------------------------
[2021-05-03 12:23:36] cmb@php.net
Is this still an issue with any of the actively supported PHP
versions[1]?
[1] <https://www.php.net/supported-versions.php>
------------------------------------------------------------------------
[2008-01-14 12:58:24] csaba at alum dot mit dot edu
Description:
------------
If an event sink is set on IE, and then a new window is created by that IE (by clicking on a link
with target=_blank, say), then NewWindow2 fires. By replacing the first argument to NewWindow2 (via
set_variant) it is possible to identify the pending new ie and to assign a sink, $sink2, to it).
The problem is that the $sink2->ie is somehow corrupted to such an extent that trying to access
anything on it hangs ie badly.
There is a 2nd less severe but still significant problem: If the bug causing 2 lines just above the
print "\n"; in BeforeNavigate2 are commented out, then the PHP code will terminate if
either instance of IE is closed. However, there is also an error genereated at the same time (the
specific error varies, but I suspect that it has to do with cleanup of the COM objects).
Reproduce code:
---------------
<?php
// set_variant bug testing
$aES = array(); // global array of IE event sinks
$newIEpage = "<body " .
"onload='document.links[0].click()'>" .
"<a target=_blank " .
"href='http://google.com'>Goog</a></body>";
$ie = new COM("InternetExplorer.Application");
sink_ie($ie);
$ie->visible = true;
$ie->Navigate2("about:blank");
while ($ie->ReadyState<4) com_message_pump(200);
$ie->Navigate2("javascript:\"$newIEpage\"");
$ie->document->title = "variant_set Launcher";
$keepLooping = true;
while ($keepLooping) com_message_pump(200);
print "Exiting";
class mysink {
public $ie = null; // reqd for evt sink to function
function __construct($ie) { $this->ie = $ie; }
public function BeforeNavigate2 (
$ie, $url, $flags, $targetFrameName,
$postData, $headers, &$cancel) {
print __FUNCTION__ . ": " . typename($ie) . ", ";
print $ie->hwnd . ", rs: " . $ie->ReadyState;
print "; " . $url . "\n";
global $aES;
print " Sink count: " . sizeof($aES);
print ", this->ie: ";
print typename($this->ie) . ", "; // produces bug
print $this->ie->hwnd; // produces bug
print "\n";
}
public function NewWindow2 (&$newIe, $cancel) {
$ie = new COM("InternetExplorer.Application");
print "NewWindow2: ";
variant_set($newIe, $ie);
$sink2 = sink_ie($ie);
print $sink2->ie->hwnd . "\n";
}
public function DownloadComplete() {
print __FUNCTION__ . "\n"; }
public function DocumentComplete($dom, $url) {
print __FUNCTION__ . ": $url\n"; }
public function onQuit() { print "Quitting\n";
$GLOBALS['keepLooping'] = false; }
}
function typename($objCOM) {
// similar to typename in vbscript
if (empty($objCOM)) return "no COM object";
if (gettype($objCOM)!="object")
return "not a COM object";
ob_start();
com_print_typeinfo($objCOM);
$typeInfo = ob_get_contents();
ob_end_clean();
$pattern = "/^\\s*class (.*) \\{/";
if (!($matchCnt = preg_match($pattern,
$typeInfo, $aMatch)))
return "Not found";
return "COM:" . $aMatch[1];
}
function sink_ie($ie) {
// sink $ie, and add to global array of sinks
global $aES;
com_event_sink ($ie, $aES[] = $sink =
new mysink($ie),
"DWebBrowserEvents2");
return $sink;
}
?>
Expected result:
----------------
This is PHP CLI code. When run from the cmd prompt, I expect two instances of IE to come up (they
do), and for the cmd prompt to display the navigation progress.
Now I could see that $sink2->ie becomes obsolete somehow (even though its hwnd is the same as the
hwnd that comes into BeforeNavigate2), but what seems really wrong is to get a hang upon trying to
do anything with that variable in BeforeNavigate2 (either $this->ie or
$aES[sizeof($aES)-1]->ie)
Actual result:
--------------
If the included script is run as is, then typename($this->ie) causes a hang. If it is commented
out, $this->ie->hwnd causes a hang. If both of these statements (the two lines before the
last print statement in BeforeNavigate2) are commented out, then both IE pages will load OK (ie. the
main bug goes away), and there will only be issues when the php code shuts down on account of one of
the two IE's being closed.
A note about the code: While it may appear somewhat convoluted, the point of the original code was
to track navigation progress within ie, and this works fine. However, when (simulated) clicking on
a link causes the browser to open a new window, then navigation tracking must continue with a new
ie, and the way to get ahold of that ie is with the NewWindow2 or NewWindow3 event, and I used the
former.
Two things need to happen in NewWindow2. The first is that the first argument to the event handler
needs to be set to an uninitiated, fresh IE. The second is that this new IE needs to be sinked.
Because we're in an event handler, globals are not so good, but since event sinks require a
reference to their COM object, the sink gets an IE variable. The variable is not superfluous: if
you make NewWindow2's final line be $sink2->ie = null; the 2nd event handler won't
function. $aES is not required in the script, but it is useful in broader schemes where one cannot
be sure whether the particular IE is already sunk (and hence one iterates through it, looking at the
handles of the associated IEs.
Csaba Gabor from Vienna
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=43838&edit=1