* Fix GH-17658: COMPersistHelper::LoadFromStream() can segfault
The actual fix is trivial, but to be able to test the behavior we have
to introduce an own COM object, since existing persistable objects
likely implement `IPersistInit`, not only `IPersist`. We also want to
avoid further test dependencies on possibly unavailable objects, such
as `Word.Application`.
To this purposes, we add a small COM in-process server, which may be
extended for other testing purposes. We keep it simple by implementing
it in C++, but without using any more sophisticated frameworks like ATL.
This component needs to be built explicitly (`nmake comtest.dll`), and
also needs to be explicitly registered (`nmake register_comtest`).
When no longer needed, it is possible to unregister the component
(`nmake unregister_comtest`).
As is, methods of PHP can never be called, because we're first trying
to read the property with the name of the method.
We fix this by first checking for `DISPATCH_METHOD` and treat that as
method call, if the method would be callable. Only otherwise we try to
access the respective property.
It needs to be noted that this breaks code which accesses a property of
an object, which defines a method of the same name. However, instances
of such classes should never be wrapped in variants, because this can't
be distinguished by COM anyway.
Closes GH-16945.
Avoid dl() in bug77578.phpt
`dl()` has known issues regarding permanent strings[1], so we better
avoid it, even if that means that we need to spawn two sub-processes.
[1] <https://github.com/php/php-src/issues/9196>
First, we fix the long standing issue that property access throws a
`com_exception` ("0x80020003: member not found), because the `HRESULT`
was not properly set after accessing the property.
Next, we fix an issue introduced as of PHP 7.0.0, where the string
length for write access had been properly adapted, but the string
length for read access had been overlooked.
Then we fix an issue introduced as of PHP 8.0.0, where new `HashTable`s
no longer set `nNextFreeElement` to zero, but to `ZEND_LONG_MIN`. This
doesn't work well with the `DISPID` lookup, which is a `LONG`.
Finally we fix a potential double-free due to erroneously destroying
the return value of `zend_read_property()`.
Closes GH-16331.
Converting PHP arrays to Variants originally supported almost arbitrary
numeric arrays, possibly filling gaps with NULL values. This is broken
as of PHP 7.0.0[1] so that the SafeArray only has as many elements as
the PHP array. Thus, unless the array is a list, some elements may be
written outside of the SafeArray data.
To avoid breaking userland code after that long time, we do not restore
the original behavior, but instead only suppress the erroneous writes.
To avoid the need to split the regression test for 32bit and 64bit
Windows, we suppress the "max number 4294967295 of elements in safe
array exceeded" warning, which only occurs for 64bit versions.
[1] <c865472ef0>
Closes GH-16309.
* Prevent direct instantiation of com_safearray_proxy
The `com_safearray_proxy` class is meant for internal usage, but so far
it was possible to instantiate it from userland, although that made no
sense. However, a while ago there was a relevant change[1], namely
that its `default_object_handlers` are now assigned when the class is
registered, while previously they only have been assigned when an
instance had been created internally. So now when freeing a manually
created object, `free_obj()` is called, although the object never has
been properly initialized (causing segfaults).
We fix this by introducing a `create_object()` handler which properly
initializes the object with dummy values. Since a manually created
`com_safearray_proxy` still does not make sense, we disallow its
instantiation.
[1] <94ee4f9834>
Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
This is mostly about minor glitches (signedness or length confusion),
but also fixes two occasions where `zend_string`s still have been
regarded as `char *`.
We also add a regression test case for failing property name lookup,
since that is the most relevant issue we're fixing here.
This also fixes skipped tests due to different naming "zend-test"
instead of "zend_test" and "PDO" instead of "pdo":
- ext/dom/tests/libxml_global_state_entity_loader_bypass.phpt
- ext/simplexml/tests/libxml_global_state_entity_loader_bypass.phpt
- ext/xmlreader/tests/libxml_global_state_entity_loader_bypass.phpt
- ext/zend_test/tests/observer_sqlite_create_function.phpt
EXTENSIONS section is used for the Windows build to load the non-static
extensions.
Closes GH-13276
Multiple tests had to be changed to escape the arguments in shell
commands. Some tests are skipped because they behave differently with
spaces in the path versus without. One notable example of this is the
hashbang test which does not work because spaces in hashbangs paths are
not supported in Linux.
Co-authored-by: Michael Voříšek <mvorisek@mvorisek.cz>
We add support for creating `VT_ERROR` variants via `__construct()`,
and allow casting to int via `variant_cast()` and `variant_set_type()`.
We do not, however, allow type conversion by other means, to avoid
otherwise easily introduced type confusion. VB(A) also only allows
explicit type conversion.
We also introduce `DISP_E_PARAMNOTFOUND` which might be the most
important `scode` for this purpose, since this allows to skip optional
parameters in method calls.
Closes GH-8886.
The test as is can only work if com_dotnet is built dynamically, and
not already loaded via the php.ini file. While this is given on
AppVeyor, it may not be given in other environments.
Closes GH-8879.
When casting a `variant` to `int`, we need to heed the proper `zval`
type, which is an signed 64bit integer on x64, while `VT_INT` is only
a signed 32bit integer.
Closes GH-8779.
We only load a minimum set of extensions, and rely on dynamic loading
of others due to `--EXTENSION--` triggers. We do not run the imap,
ldap and snmp test suites, because most of the tests would be skipped
after timeouts anyway.
Closes GH-7150.
PHP error messages should not contain line breaks, so we remove these
from the Windows specific error messages. We also remove trailing
periods for the same reason.
Closes GH-6423.
`ITypeInfo_GetIDsOfNames()` is supposed to fail with `E_NOTIMPL` for
out-of-process servers, thus we should not remove the already available
typeinfo of the object in this case.
We also properly free the `byref_vals`.
A `BSTR` is similar to a `zend_string`; it stores the length of the
string just before the actual string, and thus the string may contain
NUL bytes. However, `php_com_olestring_to_string()` is supposed to
deal with arbitrary `OLECHAR*`s which may not be `BSTR`s, so we
introduce `php_com_bstr_to_string()` and use it for the only case where
we actually have to deal with `BSTR`s which may contain NUL bytes.
Contrary to `php_com_olestring_to_string()` we return a `zend_string`,
so we can save the re-allocation when converting to a `zval`.
We also cater to `php_com_string_to_olestring()` not being binary safe,
with basically the same fix we did for `php_com_olestring_to_string()`.
We substitute the construction magic with standard constructors, move
the ZPP checks to the beginning of the ctors, and also let the function
entries be generated from the stubs.
The skip message must start with the word 'skip', otherwise the test will not be skipped.
*Before:*
Running selected tests.
TEST 1/1 [ext/com_dotnet/tests/bug79332.phpt]
========DIFF========
001+ Fatal error: Uncaught Error: Class 'COMPersistHelper' not found in /srv/php/ext/com_dotnet/tests/bug79332.php:2
001- A com_exception has been thrown
002+ Stack trace:
003+ #0 {main}
004+ thrown in /srv/php/ext/com_dotnet/tests/bug79332.php on line 2
========DONE========
FAIL Bug #79332 (php_istreams are never freed) [ext/com_dotnet/tests/bug79332.phpt]
*After:*
Running selected tests.
SKIP Bug #79332 (php_istreams are never freed) [ext/com_dotnet/tests/bug79332.phpt] reason: com_dotnet extension not available