From a124372175471b4b536f9cacaee27d1e65af1a32 Mon Sep 17 00:00:00 2001 From: Joe George Date: Tue, 10 May 2016 14:21:09 -0400 Subject: Backport PHP7 support --- php/src/php5/Operation.cpp | 909 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 909 insertions(+) create mode 100644 php/src/php5/Operation.cpp (limited to 'php/src/php5/Operation.cpp') diff --git a/php/src/php5/Operation.cpp b/php/src/php5/Operation.cpp new file mode 100644 index 00000000000..164f6003011 --- /dev/null +++ b/php/src/php5/Operation.cpp @@ -0,0 +1,909 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace IcePHP; +using namespace Slice::PHP; + +extern "C" +{ +ZEND_FUNCTION(IcePHP_Operation_call); +} + +namespace IcePHP +{ + +class ParamInfo : public IceUtil::Shared +{ +public: + + TypeInfoPtr type; + bool optional; + int tag; + int pos; +}; +typedef IceUtil::Handle ParamInfoPtr; +typedef list ParamInfoList; + +// +// Receives an out parameter or return value. +// +class ResultCallback : public UnmarshalCallback +{ +public: + + ResultCallback(); + ~ResultCallback(); + + virtual void unmarshaled(zval*, zval*, void* TSRMLS_DC); + + void unset(TSRMLS_D); + + zval* zv; +}; +typedef IceUtil::Handle ResultCallbackPtr; +typedef vector ResultCallbackList; + +// +// Encapsulates attributes of an operation. +// +class OperationI : public Operation +{ +public: + + OperationI(const char*, Ice::OperationMode, Ice::OperationMode, Ice::FormatType, zval*, zval*, zval*, zval* + TSRMLS_DC); + ~OperationI(); + + virtual zend_function* function(); + + string name; // On-the-wire name. + Ice::OperationMode mode; + Ice::OperationMode sendMode; + Ice::FormatType format; + ParamInfoList inParams; + ParamInfoList optionalInParams; + ParamInfoList outParams; + ParamInfoList optionalOutParams; + ParamInfoPtr returnType; + ExceptionInfoList exceptions; + bool sendsClasses; + bool returnsClasses; + int numParams; + +private: + + zend_internal_function* _zendFunction; + + static void convertParams(zval*, ParamInfoList&, bool& TSRMLS_DC); + static ParamInfoPtr convertParam(zval*, int TSRMLS_DC); + static void getArgInfo(zend_arg_info&, const ParamInfoPtr&, bool); +}; +typedef IceUtil::Handle OperationIPtr; + +// +// The base class for client-side invocations. +// +class Invocation : virtual public IceUtil::Shared +{ +public: + + Invocation(const Ice::ObjectPrx&, const CommunicatorInfoPtr& TSRMLS_DC); + + virtual void invoke(INTERNAL_FUNCTION_PARAMETERS) = 0; + +protected: + + Ice::ObjectPrx _prx; + CommunicatorInfoPtr _communicator; +#ifdef ZTS + TSRMLS_D; +#endif +}; +typedef IceUtil::Handle InvocationPtr; + +// +// TypedInvocation uses the information in the given operation to validate, marshal, and unmarshal +// parameters and exceptions. +// +class TypedInvocation : virtual public Invocation +{ +public: + + TypedInvocation(const Ice::ObjectPrx&, const CommunicatorInfoPtr&, const OperationIPtr& TSRMLS_DC); + +protected: + + OperationIPtr _op; + + bool prepareRequest(int, zval**, Ice::OutputStreamPtr&, pair& TSRMLS_DC); + void unmarshalResults(int, zval**, zval*, const pair& TSRMLS_DC); + zval* unmarshalException(const pair& TSRMLS_DC); + bool validateException(const ExceptionInfoPtr& TSRMLS_DC) const; + void checkTwowayOnly(const Ice::ObjectPrx&) const; +}; + +// +// A synchronous typed invocation. +// +class SyncTypedInvocation : virtual public TypedInvocation +{ +public: + + SyncTypedInvocation(const Ice::ObjectPrx&, const CommunicatorInfoPtr&, const OperationIPtr& TSRMLS_DC); + + virtual void invoke(INTERNAL_FUNCTION_PARAMETERS); +}; + +class UserExceptionReaderFactoryI : public Ice::UserExceptionReaderFactory +{ +public: + + UserExceptionReaderFactoryI(const CommunicatorInfoPtr& communicator TSRMLS_DC) : + _communicator(communicator) + { +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif + } + + virtual void createAndThrow(const string& id) const + { + ExceptionInfoPtr info = getExceptionInfo(id TSRMLS_CC); + if(info) + { + throw ExceptionReader(_communicator, info TSRMLS_CC); + } + } + +private: + + const CommunicatorInfoPtr _communicator; +#if ZTS + TSRMLS_D; +#endif +}; + +} + +// +// ResultCallback implementation. +// +IcePHP::ResultCallback::ResultCallback() : + zv(0) +{ +} + +IcePHP::ResultCallback::~ResultCallback() +{ + if(zv) + { + zval_ptr_dtor(&zv); + } +} + +void +IcePHP::ResultCallback::unmarshaled(zval* val, zval*, void* TSRMLS_DC) +{ + // + // Keep a reference to the unmarshaled value. + // + zv = val; + Z_ADDREF_P(zv); +} + +void +IcePHP::ResultCallback::unset(TSRMLS_D) +{ + MAKE_STD_ZVAL(zv); + assignUnset(zv TSRMLS_CC); +} + +// +// OperationI implementation. +// +IcePHP::OperationI::OperationI(const char* n, Ice::OperationMode m, Ice::OperationMode sm, Ice::FormatType f, zval* in, + zval* out, zval* ret, zval* ex TSRMLS_DC) : + name(n), mode(m), sendMode(sm), format(f), _zendFunction(0) +{ + // + // inParams + // + sendsClasses = false; + if(in) + { + convertParams(in, inParams, sendsClasses TSRMLS_CC); + } + + // + // outParams + // + returnsClasses = false; + if(out) + { + convertParams(out, outParams, returnsClasses TSRMLS_CC); + } + + // + // returnType + // + if(ret) + { + returnType = convertParam(ret, 0 TSRMLS_CC); + if(!returnsClasses) + { + returnsClasses = returnType->type->usesClasses(); + } + } + + numParams = static_cast(inParams.size() + outParams.size()); + + class SortFn + { + public: + static bool compare(const ParamInfoPtr& lhs, const ParamInfoPtr& rhs) + { + return lhs->tag < rhs->tag; + } + + static bool isRequired(const ParamInfoPtr& i) + { + return !i->optional; + } + }; + + // + // The inParams list represents the parameters in the order of declaration. + // We also need a sorted list of optional parameters. + // + ParamInfoList l = inParams; + copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalInParams)); + optionalInParams.sort(SortFn::compare); + + // + // The outParams list represents the parameters in the order of declaration. + // We also need a sorted list of optional parameters. If the return value is + // optional, we must include it in this list. + // + l = outParams; + copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalOutParams)); + if(returnType && returnType->optional) + { + optionalOutParams.push_back(returnType); + } + optionalOutParams.sort(SortFn::compare); + + // + // exceptions + // + if(ex) + { + HashTable* arr = Z_ARRVAL_P(ex); + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + void* data; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast(data); + ExceptionInfoPtr i = Wrapper::value(*val TSRMLS_CC); + exceptions.push_back(i); + zend_hash_move_forward_ex(arr, &pos); + } + } +} + +IcePHP::OperationI::~OperationI() +{ + if(_zendFunction) + { + delete []_zendFunction->arg_info; + efree(const_cast(_zendFunction->function_name)); + efree(_zendFunction); + } +} + +zend_function* +IcePHP::OperationI::function() +{ + if(!_zendFunction) + { + // + // Create an array that indicates how arguments are passed to the operation. + // + zend_arg_info* argInfo = new zend_arg_info[numParams]; + + int i = 0; + ParamInfoList::const_iterator p; + for(p = inParams.begin(); p != inParams.end(); ++p, ++i) + { + getArgInfo(argInfo[i], *p, false); +#if PHP_VERSION_ID < 50400 + argInfo[i].required_num_args = static_cast(numParams); +#endif + } + for(p = outParams.begin(); p != outParams.end(); ++p, ++i) + { + getArgInfo(argInfo[i], *p, true); +#if PHP_VERSION_ID < 50400 + argInfo[i].required_num_args = static_cast(numParams); +#endif + } + + string fixed = fixIdent(name); + _zendFunction = static_cast(emalloc(sizeof(zend_internal_function))); + _zendFunction->type = ZEND_INTERNAL_FUNCTION; + _zendFunction->function_name = estrndup(STRCAST(fixed.c_str()), static_cast(fixed.length())); + _zendFunction->scope = proxyClassEntry; + _zendFunction->fn_flags = ZEND_ACC_PUBLIC; + _zendFunction->prototype = 0; + _zendFunction->num_args = static_cast(numParams); + _zendFunction->arg_info = argInfo; + _zendFunction->required_num_args = _zendFunction->num_args; +#if PHP_VERSION_ID < 50400 + _zendFunction->pass_rest_by_reference = 0; + _zendFunction->return_reference = 0; +#endif + _zendFunction->handler = ZEND_FN(IcePHP_Operation_call); + } + + return reinterpret_cast(_zendFunction); +} + +void +IcePHP::OperationI::convertParams(zval* p, ParamInfoList& params, bool& usesClasses TSRMLS_DC) +{ + assert(Z_TYPE_P(p) == IS_ARRAY); + HashTable* arr = Z_ARRVAL_P(p); + HashPosition pos; + zend_hash_internal_pointer_reset_ex(arr, &pos); + void* data; + int i = 0; + while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) + { + zval** val = reinterpret_cast(data); + ParamInfoPtr param = convertParam(*val, i TSRMLS_CC); + params.push_back(param); + if(!param->optional && !usesClasses) + { + usesClasses = param->type->usesClasses(); + } + zend_hash_move_forward_ex(arr, &pos); + ++i; + } +} + +ParamInfoPtr +IcePHP::OperationI::convertParam(zval* p, int pos TSRMLS_DC) +{ + assert(Z_TYPE_P(p) == IS_ARRAY); + HashTable* arr = Z_ARRVAL_P(p); + assert(zend_hash_num_elements(arr) == 3); + + ParamInfoPtr param = new ParamInfo; + zval** m; + + zend_hash_index_find(arr, 0, reinterpret_cast(&m)); + param->type = Wrapper::value(*m TSRMLS_CC); + zend_hash_index_find(arr, 1, reinterpret_cast(&m)); + assert(Z_TYPE_PP(m) == IS_BOOL); + param->optional = Z_BVAL_PP(m) ? true : false; + zend_hash_index_find(arr, 2, reinterpret_cast(&m)); + assert(Z_TYPE_PP(m) == IS_LONG); + param->tag = Z_LVAL_PP(m); + param->pos = pos; + + return param; +} + +void +IcePHP::OperationI::getArgInfo(zend_arg_info& arg, const ParamInfoPtr& info, bool out) +{ + arg.name = 0; + arg.class_name = 0; + arg.allow_null = 1; + + if(!info->optional) + { + const bool isArray = SequenceInfoPtr::dynamicCast(info->type) || DictionaryInfoPtr::dynamicCast(info->type); + +#if PHP_VERSION_ID < 50400 + arg.array_type_hint = isArray ? 1 : 0; + arg.return_reference = 0; +#else + arg.type_hint = isArray ? IS_ARRAY : 0; +#endif + } + else + { +#if PHP_VERSION_ID < 50400 + arg.array_type_hint = 0; + arg.return_reference = 0; +#else + arg.type_hint = 0; +#endif + } + + arg.pass_by_reference = out ? 1 : 0; +} + +// +// Invocation +// +IcePHP::Invocation::Invocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator TSRMLS_DC) : + _prx(prx), _communicator(communicator) +{ +#ifdef ZTS + this->TSRMLS_C = TSRMLS_C; +#endif +} + +// +// TypedInvocation +// +IcePHP::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator, + const OperationIPtr& op TSRMLS_DC) : + Invocation(prx, communicator TSRMLS_CC), _op(op) +{ +} + +bool +IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStreamPtr& os, + pair& params TSRMLS_DC) +{ + // + // Verify that the expected number of arguments are supplied. The context argument is optional. + // + if(argc != _op->numParams && argc != _op->numParams + 1) + { + runtimeError("incorrect number of parameters (%d)" TSRMLS_CC, argc); + return false; + } + + // + // The operation's configuration (zend_function) forces out parameters + // to be passed by reference. + // + for(int i = static_cast(_op->inParams.size()); i < _op->numParams; ++i) + { + assert(PZVAL_IS_REF(args[i])); + } + + if(!_op->inParams.empty()) + { + try + { + // + // Marshal the in parameters. + // + os = Ice::createOutputStream(_communicator->getCommunicator()); + os->startEncapsulation(_prx->ice_getEncodingVersion(), _op->format); + + ObjectMap objectMap; + ParamInfoList::iterator p; + + // + // Validate the supplied arguments. + // + for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) + { + ParamInfoPtr info = *p; + zval* arg = args[info->pos]; + if((!info->optional || !isUnset(arg TSRMLS_CC)) && !info->type->validate(arg TSRMLS_CC)) + { + invalidArgument("invalid value for argument %d in operation `%s'" TSRMLS_CC, info->pos + 1, + _op->name.c_str()); + return false; + } + } + + // + // Marshal the required parameters. + // + for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(!info->optional) + { + zval* arg = args[info->pos]; + info->type->marshal(arg, os, &objectMap, false TSRMLS_CC); + } + } + + // + // Marshal the optional parameters. + // + for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p) + { + ParamInfoPtr info = *p; + zval* arg = args[info->pos]; + if(!isUnset(arg TSRMLS_CC) && os->writeOptional(info->tag, info->type->optionalFormat())) + { + info->type->marshal(arg, os, &objectMap, true TSRMLS_CC); + } + } + + if(_op->sendsClasses) + { + os->writePendingObjects(); + } + + os->endEncapsulation(); + params = os->finished(); + } + catch(const AbortMarshaling&) + { + return false; + } + catch(const Ice::Exception& ex) + { + throwException(ex TSRMLS_CC); + return false; + } + } + + return true; +} + +void +IcePHP::TypedInvocation::unmarshalResults(int argc, zval** args, zval* ret, + const pair& bytes TSRMLS_DC) +{ + Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator->getCommunicator(), bytes); + + // + // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + SlicedDataUtil util; + assert(!is->closure()); + is->closure(&util); + + is->startEncapsulation(); + + ParamInfoList::iterator p; + + // + // These callbacks collect references to the unmarshaled values. We copy them into + // the argument list *after* any pending objects have been unmarshaled. + // + ResultCallbackList outParamCallbacks; + ResultCallbackPtr retCallback; + + outParamCallbacks.resize(_op->outParams.size()); + + // + // Unmarshal the required out parameters. + // + for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(!info->optional) + { + ResultCallbackPtr cb = new ResultCallback; + outParamCallbacks[info->pos] = cb; + info->type->unmarshal(is, cb, _communicator, 0, 0, false TSRMLS_CC); + } + } + + // + // Unmarshal the required return value, if any. + // + if(_op->returnType && !_op->returnType->optional) + { + retCallback = new ResultCallback; + _op->returnType->type->unmarshal(is, retCallback, _communicator, 0, 0, false TSRMLS_CC); + } + + // + // Unmarshal the optional results. This includes an optional return value. + // + for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) + { + ParamInfoPtr info = *p; + + ResultCallbackPtr cb = new ResultCallback; + if(_op->returnType && info->tag == _op->returnType->tag) + { + retCallback = cb; + } + else + { + outParamCallbacks[info->pos] = cb; + } + + if(is->readOptional(info->tag, info->type->optionalFormat())) + { + info->type->unmarshal(is, cb, _communicator, 0, 0, true TSRMLS_CC); + } + else + { + cb->unset(TSRMLS_C); + } + } + + if(_op->returnsClasses) + { + is->readPendingObjects(); + } + + is->endEncapsulation(); + + util.update(TSRMLS_C); + + int i = static_cast(_op->inParams.size()); + for(ResultCallbackList::iterator q = outParamCallbacks.begin(); q != outParamCallbacks.end(); ++q, ++i) + { + // + // We must explicitly destroy the existing contents of all zvals passed + // as out parameters, otherwise leaks occur. + // + zval* val = (*q)->zv; + zval_dtor(args[i]); + args[i]->value = val->value; + Z_TYPE_P(args[i]) = Z_TYPE_P(val); + zval_copy_ctor(args[i]); + } + + if(_op->returnType) + { + ret->value = retCallback->zv->value; + Z_TYPE_P(ret) = Z_TYPE_P(retCallback->zv); + zval_copy_ctor(ret); + } +} + +zval* +IcePHP::TypedInvocation::unmarshalException(const pair& bytes TSRMLS_DC) +{ + Ice::InputStreamPtr is = Ice::wrapInputStream(_communicator->getCommunicator(), bytes); + + // + // Store a pointer to a local SlicedDataUtil object as the stream's closure. + // This is necessary to support object unmarshaling (see ObjectReader). + // + SlicedDataUtil util; + assert(!is->closure()); + is->closure(&util); + + is->startEncapsulation(); + + try + { + Ice::UserExceptionReaderFactoryPtr factory = new UserExceptionReaderFactoryI(_communicator TSRMLS_CC); + is->throwException(factory); + } + catch(const ExceptionReader& r) + { + is->endEncapsulation(); + + zval* ex = r.getException(); + ExceptionInfoPtr info = r.getInfo(); + + if(validateException(info TSRMLS_CC)) + { + util.update(TSRMLS_C); + + Ice::SlicedDataPtr slicedData = r.getSlicedData(); + if(slicedData) + { + SlicedDataUtil::setMember(ex, slicedData TSRMLS_CC); + } + + return ex; + } + else + { + zval_ptr_dtor(&ex); + Ice::UnknownUserException uue(__FILE__, __LINE__, + "operation raised undeclared exception `" + info->id + "'"); + return convertException(uue TSRMLS_CC); + } + } + + // + // Getting here should be impossible: we can get here only if the + // sender has marshaled a sequence of type IDs, none of which we + // have a factory for. This means that sender and receiver disagree + // about the Slice definitions they use. + // + Ice::UnknownUserException uue(__FILE__, __LINE__, "unknown exception"); + return convertException(uue TSRMLS_CC); +} + +bool +IcePHP::TypedInvocation::validateException(const ExceptionInfoPtr& info TSRMLS_DC) const +{ + for(ExceptionInfoList::const_iterator p = _op->exceptions.begin(); p != _op->exceptions.end(); ++p) + { + if(info->isA((*p)->id)) + { + return true; + } + } + + return false; +} + +void +IcePHP::TypedInvocation::checkTwowayOnly(const Ice::ObjectPrx& proxy) const +{ + if((_op->returnType || !_op->outParams.empty()) && !proxy->ice_isTwoway()) + { + Ice::TwowayOnlyException ex(__FILE__, __LINE__); + ex.operation = _op->name; + throw ex; + } +} + +// +// SyncTypedInvocation +// +IcePHP::SyncTypedInvocation::SyncTypedInvocation(const Ice::ObjectPrx& prx, const CommunicatorInfoPtr& communicator, + const OperationIPtr& op TSRMLS_DC) : + Invocation(prx, communicator TSRMLS_CC), TypedInvocation(prx, communicator, op TSRMLS_CC) +{ +} + +void +IcePHP::SyncTypedInvocation::invoke(INTERNAL_FUNCTION_PARAMETERS) +{ + // + // Retrieve the arguments. + // + zval*** args = static_cast(emalloc(ZEND_NUM_ARGS() * sizeof(zval**))); + AutoEfree autoArgs(args); // Call efree on return + if(zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) + { + runtimeError("unable to get arguments" TSRMLS_CC); + return; + } + + Ice::OutputStreamPtr os; + pair params; + if(!prepareRequest(ZEND_NUM_ARGS(), *args, os, params TSRMLS_CC)) + { + return; + } + + bool hasCtx = false; + Ice::Context ctx; + if(ZEND_NUM_ARGS() == _op->numParams + 1) + { + if(!extractStringMap(*args[ZEND_NUM_ARGS() - 1], ctx TSRMLS_CC)) + { + return; + } + hasCtx = true; + } + + try + { + checkTwowayOnly(_prx); + + // + // Invoke the operation. + // + vector result; + bool status; + { + if(hasCtx) + { + status = _prx->ice_invoke(_op->name, _op->sendMode, params, result, ctx); + } + else + { + status = _prx->ice_invoke(_op->name, _op->sendMode, params, result); + } + } + + // + // Process the reply. + // + if(_prx->ice_isTwoway()) + { + if(!status) + { + // + // Unmarshal a user exception. + // + pair rb(0, 0); + if(!result.empty()) + { + rb.first = &result[0]; + rb.second = &result[0] + result.size(); + } + + zval* ex = unmarshalException(rb TSRMLS_CC); + if(ex) + { + zend_throw_exception_object(ex TSRMLS_CC); + } + } + else if(!_op->outParams.empty() || _op->returnType) + { + // + // Unmarshal the results. + // + pair rb(0, 0); + if(!result.empty()) + { + rb.first = &result[0]; + rb.second = &result[0] + result.size(); + } + unmarshalResults(ZEND_NUM_ARGS(), *args, return_value, rb TSRMLS_CC); + } + } + } + catch(const AbortMarshaling&) + { + } + catch(const Ice::Exception& ex) + { + throwException(ex TSRMLS_CC); + } +} + +ZEND_FUNCTION(IcePHP_defineOperation) +{ + zval* cls; + char* name; + int nameLen; + long mode; + long sendMode; + long format; + zval* inParams; + zval* outParams; + zval* returnType; + zval* exceptions; + + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast("osllla!a!a!a!"), &cls, &name, &nameLen, + &mode, &sendMode, &format, &inParams, &outParams, &returnType, &exceptions) == FAILURE) + { + return; + } + + TypeInfoPtr type = Wrapper::value(cls TSRMLS_CC); + ClassInfoPtr c = ClassInfoPtr::dynamicCast(type); + assert(c); + + OperationIPtr op = new OperationI(name, static_cast(mode), + static_cast(sendMode), static_cast(format), + inParams, outParams, returnType, exceptions TSRMLS_CC); + + c->addOperation(name, op); +} + +ZEND_FUNCTION(IcePHP_Operation_call) +{ + Ice::ObjectPrx proxy; + ClassInfoPtr cls; + CommunicatorInfoPtr comm; +#ifndef NDEBUG + bool b = +#endif + fetchProxy(getThis(), proxy, cls, comm TSRMLS_CC); + assert(b); + assert(proxy); + assert(cls); + + OperationPtr op = cls->getOperation(get_active_function_name(TSRMLS_C)); + assert(op); // handleGetMethod should have already verified the operation's existence. + OperationIPtr opi = OperationIPtr::dynamicCast(op); + assert(opi); + + InvocationPtr inv = new SyncTypedInvocation(proxy, comm, opi TSRMLS_CC); + inv->invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} -- cgit v1.2.3 From e40a438a70f06fb163020eb3b2cb42e0e18eb3ed Mon Sep 17 00:00:00 2001 From: Joe George Date: Tue, 31 May 2016 15:58:29 -0400 Subject: Fix ICE-7163 - Printing types is more forgiving and will not throw an exception if there is bogus data. - Fix several print statements to print the correct class name. --- php/src/php5/Operation.cpp | 6 +- php/src/php5/Types.cpp | 148 ++++++++++++++++++++++++++++++--------------- php/src/php5/Types.h | 16 ++--- php/src/php7/Operation.cpp | 2 +- php/src/php7/Types.cpp | 147 ++++++++++++++++++++++++++++---------------- php/src/php7/Types.h | 16 ++--- php/src/php7/Util.cpp | 14 ++--- 7 files changed, 222 insertions(+), 127 deletions(-) (limited to 'php/src/php5/Operation.cpp') diff --git a/php/src/php5/Operation.cpp b/php/src/php5/Operation.cpp index 164f6003011..6257494386c 100644 --- a/php/src/php5/Operation.cpp +++ b/php/src/php5/Operation.cpp @@ -460,7 +460,7 @@ IcePHP::TypedInvocation::TypedInvocation(const Ice::ObjectPrx& prx, const Commun } bool -IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStreamPtr& os, +IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStreamPtr& os, pair& params TSRMLS_DC) { // @@ -501,7 +501,7 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval** args, Ice::OutputStream { ParamInfoPtr info = *p; zval* arg = args[info->pos]; - if((!info->optional || !isUnset(arg TSRMLS_CC)) && !info->type->validate(arg TSRMLS_CC)) + if((!info->optional || !isUnset(arg TSRMLS_CC)) && !info->type->validate(arg, false TSRMLS_CC)) { invalidArgument("invalid value for argument %d in operation `%s'" TSRMLS_CC, info->pos + 1, _op->name.c_str()); @@ -770,7 +770,7 @@ IcePHP::SyncTypedInvocation::invoke(INTERNAL_FUNCTION_PARAMETERS) runtimeError("unable to get arguments" TSRMLS_CC); return; } - + Ice::OutputStreamPtr os; pair params; if(!prepareRequest(ZEND_NUM_ARGS(), *args, os, params TSRMLS_CC)) diff --git a/php/src/php5/Types.cpp b/php/src/php5/Types.cpp index 94b7cfd4e2a..563aabba5fb 100644 --- a/php/src/php5/Types.cpp +++ b/php/src/php5/Types.cpp @@ -658,7 +658,7 @@ IcePHP::PrimitiveInfo::getId() const } bool -IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) +IcePHP::PrimitiveInfo::validate(zval* zv, bool throwException TSRMLS_DC) { switch(kind) { @@ -666,8 +666,11 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) { if(Z_TYPE_P(zv) != IS_BOOL) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected boolean value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected boolean value but received %s" TSRMLS_CC, s.c_str()); + } return false; } break; @@ -677,13 +680,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected byte value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected byte value but received %s" TSRMLS_CC, s.c_str()); + } return false; } long val = Z_LVAL_P(zv); if(val < 0 || val > 255) { - invalidArgument("value %ld is out of range for a byte" TSRMLS_CC, val); + if(throwException) + { + invalidArgument("value %ld is out of range for a byte" TSRMLS_CC, val); + } return false; } break; @@ -693,13 +702,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected short value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected short value but received %s" TSRMLS_CC, s.c_str()); + } return false; } long val = Z_LVAL_P(zv); if(val < SHRT_MIN || val > SHRT_MAX) { - invalidArgument("value %ld is out of range for a short" TSRMLS_CC, val); + if(throwException) + { + invalidArgument("value %ld is out of range for a short" TSRMLS_CC, val); + } return false; } break; @@ -709,13 +724,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected int value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected int value but received %s" TSRMLS_CC, s.c_str()); + } return false; } long val = Z_LVAL_P(zv); if(val < INT_MIN || val > INT_MAX) { - invalidArgument("value %ld is out of range for an int" TSRMLS_CC, val); + if(throwException) + { + invalidArgument("value %ld is out of range for an int" TSRMLS_CC, val); + } return false; } break; @@ -729,7 +750,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_STRING) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected long value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected long value but received %s" TSRMLS_CC, s.c_str()); + } return false; } Ice::Long val; @@ -742,7 +766,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) string sval(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); if(!IceUtilInternal::stringToInt64(sval, val)) { - invalidArgument("invalid long value `%s'" TSRMLS_CC, Z_STRVAL_P(zv)); + if(throwException) + { + invalidArgument("invalid long value `%s'" TSRMLS_CC, Z_STRVAL_P(zv)); + } return false; } } @@ -753,13 +780,16 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected float value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected float value but received %s" TSRMLS_CC, s.c_str()); + } return false; } if(Z_TYPE_P(zv) == IS_DOUBLE) { double val = Z_DVAL_P(zv); - return (val <= numeric_limits::max() && val >= -numeric_limits::max()) || + return (val <= numeric_limits::max() && val >= -numeric_limits::max()) || #if defined(_MSC_VER) && (_MSC_VER <= 1700) !_finite(val); #else @@ -773,7 +803,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected double value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected double value but received %s" TSRMLS_CC, s.c_str()); + } return false; } break; @@ -783,7 +816,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv TSRMLS_DC) if(Z_TYPE_P(zv) != IS_STRING && Z_TYPE_P(zv) != IS_NULL) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected string value but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + invalidArgument("expected string value but received %s" TSRMLS_CC, s.c_str()); + } return false; } break; @@ -1045,7 +1081,7 @@ IcePHP::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalC void IcePHP::PrimitiveInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << ""; return; @@ -1100,7 +1136,7 @@ IcePHP::EnumInfo::getId() const } bool -IcePHP::EnumInfo::validate(zval* zv TSRMLS_DC) +IcePHP::EnumInfo::validate(zval* zv, bool TSRMLS_DC) { if(Z_TYPE_P(zv) == IS_LONG) { @@ -1161,7 +1197,7 @@ IcePHP::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallba void IcePHP::EnumInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << ""; return; @@ -1309,7 +1345,7 @@ IcePHP::StructInfo::getId() const } bool -IcePHP::StructInfo::validate(zval* zv TSRMLS_DC) +IcePHP::StructInfo::validate(zval* zv, bool throwException TSRMLS_DC) { if(Z_TYPE_P(zv) == IS_NULL) { @@ -1317,8 +1353,11 @@ IcePHP::StructInfo::validate(zval* zv TSRMLS_DC) } else if(Z_TYPE_P(zv) != IS_OBJECT) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, s.c_str()); + } return false; } @@ -1328,7 +1367,10 @@ IcePHP::StructInfo::validate(zval* zv TSRMLS_DC) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != zce) { - invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, ce->name); + if(throwException) + { + invalidArgument("expected struct value of type %s but received %s" TSRMLS_CC, zce->name, ce->name); + } return false; } @@ -1416,7 +1458,7 @@ IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* } zval** val = reinterpret_cast(data); - if(!member->type->validate(*val TSRMLS_CC)) + if(!member->type->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, id.c_str(), member->name.c_str()); throw AbortMarshaling(); @@ -1469,7 +1511,7 @@ IcePHP::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCall void IcePHP::StructInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << ""; return; @@ -1534,7 +1576,7 @@ IcePHP::SequenceInfo::getId() const } bool -IcePHP::SequenceInfo::validate(zval* zv TSRMLS_DC) +IcePHP::SequenceInfo::validate(zval* zv, bool TSRMLS_DC) { return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; } @@ -1611,7 +1653,7 @@ IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMa while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!elementType->validate(*val TSRMLS_CC)) + if(!elementType->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value for sequence element `%s'" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); @@ -1668,7 +1710,7 @@ IcePHP::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCa void IcePHP::SequenceInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << ""; return; @@ -1745,7 +1787,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1767,7 +1809,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1787,7 +1829,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1807,7 +1849,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1827,7 +1869,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1860,7 +1902,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1891,7 +1933,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -1922,7 +1964,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* while(zend_hash_get_current_data_ex(arr, &data, &pos) != FAILURE) { zval** val = reinterpret_cast(data); - if(!pi->validate(*val TSRMLS_CC)) + if(!pi->validate(*val, true TSRMLS_CC)) { throw AbortMarshaling(); } @@ -2094,7 +2136,7 @@ IcePHP::DictionaryInfo::getId() const } bool -IcePHP::DictionaryInfo::validate(zval* zv TSRMLS_DC) +IcePHP::DictionaryInfo::validate(zval* zv, bool TSRMLS_DC) { return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; } @@ -2243,7 +2285,7 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object // // Marshal the key. // - if(!keyType->validate(zkey TSRMLS_CC)) + if(!keyType->validate(zkey, false TSRMLS_CC)) { invalidArgument("invalid key in `%s' element" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); @@ -2253,7 +2295,7 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object // // Marshal the value. // - if(!valueType->validate(*val TSRMLS_CC)) + if(!valueType->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value in `%s' element" TSRMLS_CC, id.c_str()); throw AbortMarshaling(); @@ -2328,7 +2370,7 @@ IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const Unmarshal void IcePHP::DictionaryInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << ""; return; @@ -2519,7 +2561,7 @@ IcePHP::ClassInfo::getId() const } bool -IcePHP::ClassInfo::validate(zval* val TSRMLS_DC) +IcePHP::ClassInfo::validate(zval* val, bool TSRMLS_DC) { if(Z_TYPE_P(val) == IS_OBJECT) { @@ -2568,7 +2610,7 @@ IcePHP::ClassInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* } assert(Z_TYPE_P(zv) == IS_OBJECT); // validate() should have caught this. - assert(checkClass(Z_OBJCE_P(zv), zce)); // validate() should have caught this. + assert(checkClass(Z_OBJCE_P(zv), const_cast(zce))); // validate() should have caught this. // // Ice::ObjectWriter is a subclass of Ice::Object that wraps a PHP object for marshaling. @@ -2611,7 +2653,7 @@ IcePHP::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb void IcePHP::ClassInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << ""; return; @@ -2783,14 +2825,17 @@ IcePHP::ProxyInfo::getId() const } bool -IcePHP::ProxyInfo::validate(zval* zv TSRMLS_DC) +IcePHP::ProxyInfo::validate(zval* zv, bool throwException TSRMLS_DC) { if(Z_TYPE_P(zv) != IS_NULL) { if(Z_TYPE_P(zv) != IS_OBJECT || (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) != proxyClassEntry)) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected proxy value or null but received %s" TSRMLS_CC, s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected proxy value or null but received %s" TSRMLS_CC, s.c_str()); + } return false; } } @@ -2891,7 +2936,7 @@ IcePHP::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb void IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* TSRMLS_DC) { - if(!validate(zv TSRMLS_CC)) + if(!validate(zv, false TSRMLS_CC)) { out << ""; return; @@ -3019,7 +3064,7 @@ IcePHP::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMem continue; } - if(!member->type->validate(*val TSRMLS_CC)) + if(!member->type->validate(*val, false TSRMLS_CC)) { invalidArgument("invalid value for %s member `%s'" TSRMLS_CC, _info->id.c_str(), member->name.c_str()); @@ -3280,10 +3325,14 @@ IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const Communicat void IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out TSRMLS_DC) { + out << "exception " << id; + out.sb(); + if(Z_TYPE_P(zv) != IS_OBJECT) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected exception value of type %s but received %s" TSRMLS_CC, zce->name, s.c_str()); + out << nl << "expected exception value of type " << zce->name << " but received " << s; + out.eb(); return; } @@ -3293,7 +3342,8 @@ IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out TSRMLS_DC) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != zce) { - invalidArgument("expected exception value of type %s but received %s" TSRMLS_CC, zce->name, ce->name); + out << nl << "expected exception value of type " << zce->name << " but received " << ce->name; + out.eb(); return; } diff --git a/php/src/php5/Types.h b/php/src/php5/Types.h index e540d49ae01..4968b26a160 100644 --- a/php/src/php5/Types.h +++ b/php/src/php5/Types.h @@ -111,7 +111,7 @@ public: virtual std::string getId() const = 0; - virtual bool validate(zval* TSRMLS_DC) = 0; + virtual bool validate(zval*, bool TSRMLS_DC) = 0; virtual bool variableLength() const = 0; virtual int wireSize() const = 0; @@ -150,7 +150,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -189,7 +189,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -235,7 +235,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -275,7 +275,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -315,7 +315,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -388,7 +388,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; @@ -440,7 +440,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval* TSRMLS_DC); + virtual bool validate(zval*, bool TSRMLS_DC); virtual bool variableLength() const; virtual int wireSize() const; diff --git a/php/src/php7/Operation.cpp b/php/src/php7/Operation.cpp index 62e9ae4c30c..73ee697c470 100644 --- a/php/src/php7/Operation.cpp +++ b/php/src/php7/Operation.cpp @@ -463,7 +463,7 @@ IcePHP::TypedInvocation::prepareRequest(int argc, zval* args, Ice::OutputStreamP zval* arg = &args[info->pos]; assert(!Z_ISREF_P(arg)); - if((!info->optional || !isUnset(arg)) && !info->type->validate(arg)) + if((!info->optional || !isUnset(arg)) && !info->type->validate(arg, false)) { invalidArgument("invalid value for argument %d in operation `%s'", info->pos + 1, _op->name.c_str()); diff --git a/php/src/php7/Types.cpp b/php/src/php7/Types.cpp index 6fa993d360c..a29dade9b50 100644 --- a/php/src/php7/Types.cpp +++ b/php/src/php7/Types.cpp @@ -614,7 +614,7 @@ IcePHP::PrimitiveInfo::getId() const } bool -IcePHP::PrimitiveInfo::validate(zval* zv) +IcePHP::PrimitiveInfo::validate(zval* zv, bool throwException) { switch(kind) { @@ -623,7 +623,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(!(Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE)) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected boolean value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected boolean value but received %s", s.c_str()); + } return false; } break; @@ -633,13 +636,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected byte value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected byte value but received %s", s.c_str()); + } return false; } long val = static_cast(Z_LVAL_P(zv)); if(val < 0 || val > 255) { - invalidArgument("value %ld is out of range for a byte", val); + if(throwException) + { + invalidArgument("value %ld is out of range for a byte", val); + } return false; } break; @@ -649,13 +658,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected short value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected short value but received %s", s.c_str()); + } return false; } zend_long val = Z_LVAL_P(zv); if(val < SHRT_MIN || val > SHRT_MAX) { - invalidArgument("value %ld is out of range for a short", val); + if(throwException) + { + invalidArgument("value %ld is out of range for a short", val); + } return false; } break; @@ -665,13 +680,19 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected int value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected int value but received %s", s.c_str()); + } return false; } zend_long val = Z_LVAL_P(zv); if(val < INT_MIN || val > INT_MAX) { - invalidArgument("value %ld is out of range for an int", val); + if(throwException) + { + invalidArgument("value %ld is out of range for an int", val); + } return false; } break; @@ -685,7 +706,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(Z_TYPE_P(zv) != IS_LONG && Z_TYPE_P(zv) != IS_STRING) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected long value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected long value but received %s", s.c_str()); + } return false; } @@ -695,7 +719,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv) string sval(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); if(!IceUtilInternal::stringToInt64(sval, val)) { - invalidArgument("invalid long value `%s'", Z_STRVAL_P(zv)); + if(throwException) + { + invalidArgument("invalid long value `%s'", Z_STRVAL_P(zv)); + } return false; } } @@ -706,7 +733,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected float value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected float value but received %s", s.c_str()); + } return false; } if(Z_TYPE_P(zv) == IS_DOUBLE) @@ -726,7 +756,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(Z_TYPE_P(zv) != IS_DOUBLE && Z_TYPE_P(zv) != IS_LONG) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected double value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected double value but received %s", s.c_str()); + } return false; } break; @@ -736,7 +769,10 @@ IcePHP::PrimitiveInfo::validate(zval* zv) if(Z_TYPE_P(zv) != IS_STRING && Z_TYPE_P(zv) != IS_NULL) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected string value but received %s", s.c_str()); + if(throwException) + { + invalidArgument("expected string value but received %s", s.c_str()); + } return false; } break; @@ -996,7 +1032,7 @@ IcePHP::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalC void IcePHP::PrimitiveInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory*) { - if(!validate(zv)) + if(!validate(zv, false)) { out << ""; return; @@ -1045,7 +1081,7 @@ IcePHP::EnumInfo::getId() const } bool -IcePHP::EnumInfo::validate(zval* zv) +IcePHP::EnumInfo::validate(zval* zv, bool) { if(Z_TYPE_P(zv) == IS_LONG) { @@ -1105,7 +1141,7 @@ IcePHP::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallba void IcePHP::EnumInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory*) { - if(!validate(zv)) + if(!validate(zv, false)) { out << ""; return; @@ -1255,7 +1291,7 @@ IcePHP::StructInfo::getId() const } bool -IcePHP::StructInfo::validate(zval* zv) +IcePHP::StructInfo::validate(zval* zv, bool throwException) { if(Z_TYPE_P(zv) == IS_NULL) { @@ -1263,8 +1299,11 @@ IcePHP::StructInfo::validate(zval* zv) } else if(Z_TYPE_P(zv) != IS_OBJECT) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected struct value of type %s but received %s", zce->name, s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected struct value of type %s but received %s", zce->name->val, s.c_str()); + } return false; } @@ -1274,7 +1313,7 @@ IcePHP::StructInfo::validate(zval* zv) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != zce) { - invalidArgument("expected struct value of type %s but received %s", zce->name, ce->name); + invalidArgument("expected struct value of type %s but received %s", zce->name->val, ce->name->val); return false; } @@ -1324,7 +1363,7 @@ IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* { if(object_init_ex(&_nullMarshalValue, const_cast(zce)) != SUCCESS) { - runtimeError("unable to initialize object of type %s", zce->name); + runtimeError("unable to initialize object of type %s", zce->name->val); throw AbortMarshaling(); } @@ -1366,7 +1405,7 @@ IcePHP::StructInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMap* val = Z_INDIRECT_P(val); } - if(!member->type->validate(val)) + if(!member->type->validate(val, false)) { invalidArgument("invalid value for %s member `%s'", id.c_str(), member->name.c_str()); throw AbortMarshaling(); @@ -1389,7 +1428,7 @@ IcePHP::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCall AutoDestroy destroy(&zv); if(object_init_ex(&zv, const_cast(zce)) != SUCCESS) { - runtimeError("unable to initialize object of type %s", zce->name); + runtimeError("unable to initialize object of type %s", zce->name->val); throw AbortMarshaling(); } @@ -1417,7 +1456,7 @@ IcePHP::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCall void IcePHP::StructInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) { - if(!validate(zv)) + if(!validate(zv, false)) { out << ""; return; @@ -1481,7 +1520,7 @@ IcePHP::SequenceInfo::getId() const } bool -IcePHP::SequenceInfo::validate(zval* zv) +IcePHP::SequenceInfo::validate(zval* zv, bool) { return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; } @@ -1554,7 +1593,7 @@ IcePHP::SequenceInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, ObjectMa zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!elementType->validate(val)) + if(!elementType->validate(val, false)) { invalidArgument("invalid value for sequence element `%s'", id.c_str()); throw AbortMarshaling(); @@ -1619,7 +1658,7 @@ IcePHP::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCa void IcePHP::SequenceInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) { - if(!validate(zv)) + if(!validate(zv, false)) { out << ""; return; @@ -1701,7 +1740,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -1723,7 +1762,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -1743,7 +1782,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -1763,7 +1802,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -1783,7 +1822,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -1816,7 +1855,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -1847,7 +1886,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -1878,7 +1917,7 @@ IcePHP::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, zval* zval* val; ZEND_HASH_FOREACH_VAL(arr, val) { - if(!pi->validate(val)) + if(!pi->validate(val, true)) { throw AbortMarshaling(); } @@ -2046,7 +2085,7 @@ IcePHP::DictionaryInfo::getId() const } bool -IcePHP::DictionaryInfo::validate(zval* zv) +IcePHP::DictionaryInfo::validate(zval* zv, bool) { return Z_TYPE_P(zv) == IS_NULL || Z_TYPE_P(zv) == IS_ARRAY; } @@ -2184,7 +2223,7 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object // // Marshal the key. // - if(!keyType->validate(&zkey)) + if(!keyType->validate(&zkey, false)) { invalidArgument("invalid key in `%s' element", id.c_str()); throw AbortMarshaling(); @@ -2194,7 +2233,7 @@ IcePHP::DictionaryInfo::marshal(zval* zv, const Ice::OutputStreamPtr& os, Object // // Marshal the value. // - if(!valueType->validate(val)) + if(!valueType->validate(val, false)) { invalidArgument("invalid value in `%s' element", id.c_str()); throw AbortMarshaling(); @@ -2266,7 +2305,7 @@ IcePHP::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const Unmarshal void IcePHP::DictionaryInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) { - if(!validate(zv)) + if(!validate(zv, false)) { out << ""; return; @@ -2439,7 +2478,7 @@ IcePHP::ClassInfo::getId() const } bool -IcePHP::ClassInfo::validate(zval* val) +IcePHP::ClassInfo::validate(zval* val, bool) { if(Z_TYPE_P(val) == IS_OBJECT) { @@ -2531,7 +2570,7 @@ IcePHP::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb void IcePHP::ClassInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory* history) { - if(!validate(zv)) + if(!validate(zv, false)) { out << ""; return; @@ -2705,14 +2744,17 @@ IcePHP::ProxyInfo::getId() const } bool -IcePHP::ProxyInfo::validate(zval* zv) +IcePHP::ProxyInfo::validate(zval* zv, bool throwException) { if(Z_TYPE_P(zv) != IS_NULL) { if(Z_TYPE_P(zv) != IS_OBJECT || (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJCE_P(zv) != proxyClassEntry)) { - string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected proxy value or null but received %s", s.c_str()); + if(throwException) + { + string s = zendTypeToString(Z_TYPE_P(zv)); + invalidArgument("expected proxy value or null but received %s", s.c_str()); + } return false; } } @@ -2812,7 +2854,7 @@ IcePHP::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb void IcePHP::ProxyInfo::print(zval* zv, IceUtilInternal::Output& out, PrintObjectHistory*) { - if(!validate(zv)) + if(!validate(zv, false)) { out << ""; return; @@ -2942,7 +2984,7 @@ IcePHP::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMem continue; } - if(!member->type->validate(val)) + if(!member->type->validate(val, false)) { invalidArgument("invalid value for %s member `%s'", _info->id.c_str(), member->name.c_str()); throw AbortMarshaling(); @@ -3136,7 +3178,7 @@ IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const Communicat if(object_init_ex(zv, zce) != SUCCESS) { - runtimeError("unable to initialize object of type %s", zce->name); + runtimeError("unable to initialize object of type %s", zce->name->val); throw AbortMarshaling(); } @@ -3186,10 +3228,14 @@ IcePHP::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is, const Communicat void IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out) { + out << "exception " << id; + out.sb(); + if(Z_TYPE_P(zv) != IS_OBJECT) { string s = zendTypeToString(Z_TYPE_P(zv)); - invalidArgument("expected exception value of type %s but received %s", zce->name, s.c_str()); + out << nl << "expected exception value of type " << zce->name->val << " but received " << s; + out.eb(); return; } @@ -3199,15 +3245,14 @@ IcePHP::ExceptionInfo::print(zval* zv, IceUtilInternal::Output& out) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != zce) { - invalidArgument("expected exception value of type %s but received %s", zce->name, ce->name); + out << nl << "expected exception value of type " << zce->name->val << " but received " << ce->name->val; + out.eb(); return; } PrintObjectHistory history; history.index = 0; - out << "exception " << id; - out.sb(); printMembers(zv, out, &history); out.eb(); } diff --git a/php/src/php7/Types.h b/php/src/php7/Types.h index 3a8ea345a24..ee3aa294945 100644 --- a/php/src/php7/Types.h +++ b/php/src/php7/Types.h @@ -111,7 +111,7 @@ public: virtual std::string getId() const = 0; - virtual bool validate(zval*) = 0; + virtual bool validate(zval*, bool) = 0; // Validate type data. Bool enables excpetion throwing. virtual bool variableLength() const = 0; virtual int wireSize() const = 0; @@ -150,7 +150,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval*); + virtual bool validate(zval*, bool); virtual bool variableLength() const; virtual int wireSize() const; @@ -189,7 +189,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval*); + virtual bool validate(zval*, bool); virtual bool variableLength() const; virtual int wireSize() const; @@ -235,7 +235,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval*); + virtual bool validate(zval*, bool); virtual bool variableLength() const; virtual int wireSize() const; @@ -275,7 +275,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval*); + virtual bool validate(zval*, bool); virtual bool variableLength() const; virtual int wireSize() const; @@ -315,7 +315,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval*); + virtual bool validate(zval*, bool); virtual bool variableLength() const; virtual int wireSize() const; @@ -388,7 +388,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval*); + virtual bool validate(zval*, bool); virtual bool variableLength() const; virtual int wireSize() const; @@ -440,7 +440,7 @@ public: virtual std::string getId() const; - virtual bool validate(zval*); + virtual bool validate(zval*, bool); virtual bool variableLength() const; virtual int wireSize() const; diff --git a/php/src/php7/Util.cpp b/php/src/php7/Util.cpp index 193f613f303..fa16d188475 100644 --- a/php/src/php7/Util.cpp +++ b/php/src/php7/Util.cpp @@ -80,7 +80,7 @@ getVersion(zval* zv, T& v, const char* type) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != cls) { - invalidArgument("expected an instance of %s", ce->name); + invalidArgument("expected an instance of %s", ce->name->val); return false; } @@ -125,7 +125,7 @@ createVersion(zval* zv, const T& version, const char* type) if(object_init_ex(zv, cls) != SUCCESS) { - runtimeError("unable to initialize %s", cls->name); + runtimeError("unable to initialize %s", cls->name->val); return false; } @@ -255,7 +255,7 @@ IcePHP::extractIdentity(zval* zv, Ice::Identity& id) zend_class_entry* ce = Z_OBJCE_P(zv); if(ce != cls) { - invalidArgument("expected an identity but received %s", ce->name); + invalidArgument("expected an identity but received %s", ce->name->val); return false; } @@ -595,7 +595,7 @@ IcePHP::convertException(zval* zex, const Ice::Exception& ex) { if(object_init_ex(zex, cls) != SUCCESS) { - runtimeError("unable to create exception %s", cls->name); + runtimeError("unable to create exception %s", cls->name->val); return; } if(!convertLocalException(e, zex)) @@ -609,7 +609,7 @@ IcePHP::convertException(zval* zex, const Ice::Exception& ex) assert(cls); if(object_init_ex(zex, cls) != SUCCESS) { - runtimeError("unable to create exception %s", cls->name); + runtimeError("unable to create exception %s", cls->name->val); return; } setStringMember(zex, "unknown", str); @@ -621,7 +621,7 @@ IcePHP::convertException(zval* zex, const Ice::Exception& ex) assert(cls); if(object_init_ex(zex, cls) != SUCCESS) { - runtimeError("unable to create exception %s", cls->name); + runtimeError("unable to create exception %s", cls->name->val); return; } setStringMember(zex, "unknown", str); @@ -632,7 +632,7 @@ IcePHP::convertException(zval* zex, const Ice::Exception& ex) assert(cls); if(object_init_ex(zex, cls) != SUCCESS) { - runtimeError("unable to create exception %s", cls->name); + runtimeError("unable to create exception %s", cls->name->val); return; } setStringMember(zex, "unknown", str); -- cgit v1.2.3