summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Slice/CPlusPlusUtil.cpp15
-rw-r--r--cpp/src/slice2cppe/Gen.cpp50
2 files changed, 59 insertions, 6 deletions
diff --git a/cpp/src/Slice/CPlusPlusUtil.cpp b/cpp/src/Slice/CPlusPlusUtil.cpp
index 587e184804d..524cf37ea0b 100644
--- a/cpp/src/Slice/CPlusPlusUtil.cpp
+++ b/cpp/src/Slice/CPlusPlusUtil.cpp
@@ -857,11 +857,18 @@ Slice::writeMarshalUnmarshalCode(Output& out, const TypePtr& type, const string&
{
StringList md;
md.push_back("cpp:array");
- string tmpParam = "__" + fixedParam;
- string::size_type pos = tmpParam.find("[i]");
- if(pos != string::npos)
+ string tmpParam = "__";
+ if(fixedParam.find("(*") == 0)
{
- tmpParam = tmpParam.substr(0, pos);
+ tmpParam += fixedParam.substr(2, fixedParam.size() - 3);
+ }
+ else if(fixedParam.find("[i]") != string::npos)
+ {
+ tmpParam += fixedParam.substr(0, fixedParam.size() - 5);
+ }
+ else
+ {
+ tmpParam += fixedParam;
}
out << nl << typeToString(type, md) << " " << tmpParam << ";";
out << nl << stream << deref << func << tmpParam << ");";
diff --git a/cpp/src/slice2cppe/Gen.cpp b/cpp/src/slice2cppe/Gen.cpp
index 2f367ed5f15..43e4ba1fdf8 100644
--- a/cpp/src/slice2cppe/Gen.cpp
+++ b/cpp/src/slice2cppe/Gen.cpp
@@ -799,13 +799,59 @@ Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
C << sp << nl << "void" << nl << scope.substr(2) << "__write(::IceInternal::BasicStream* __os, const "
<< scoped << "& v, " << scope << "__U__" << name << ")";
C << sb;
- writeMarshalUnmarshalCode(C, p, "v", true, "", false, p->getMetaData(), false);
+ C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(v.size());";
+ C << nl << "__os->writeSize(size);";
+ C << nl << "for(" << name << "::const_iterator p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "(*p)", true);
+ C << eb;
C << eb;
C << sp << nl << "void" << nl << scope.substr(2) << "__read(::IceInternal::BasicStream* __is, " << scoped
<< "& v, " << scope << "__U__" << name << ')';
C << sb;
- writeMarshalUnmarshalCode(C, p, "v", false, "", false, p->getMetaData(), false);
+ C << nl << "::Ice::Int sz;";
+ C << nl << "__is->readSize(sz);";
+ C << nl << name << "(sz).swap(v);";
+ if(type->isVariableLength())
+ {
+ // Protect against bogus sequence sizes.
+ C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");";
+ }
+ else
+ {
+ C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");";
+ }
+ C << nl << "for(" << name << "::iterator p = v.begin(); p != v.end(); ++p)";
+ C << sb;
+ writeMarshalUnmarshalCode(C, type, "(*p)", false);
+
+ //
+ // After unmarshaling each element, check that there are still enough bytes left in the stream
+ // to unmarshal the remainder of the sequence, and decrement the count of elements
+ // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences
+ // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to
+ // abort unmarshaling for bogus sequence sizes at the earliest possible moment.
+ // (For fixed-length sequences, we don't need to do this because the prediction of how many
+ // bytes will be taken up by the sequence is accurate.)
+ //
+ if(type->isVariableLength())
+ {
+ if(!SequencePtr::dynamicCast(type))
+ {
+ //
+ // No need to check for directly nested sequences because, at the start of each
+ // sequence, we check anyway.
+ //
+ C << nl << "__is->checkSeq();";
+ }
+ C << nl << "__is->endElement();";
+ }
+ C << eb;
+ if(type->isVariableLength())
+ {
+ C << nl << "__is->endSeq(sz);";
+ }
C << eb;
}
else if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)