Currently the C++ bindings of KeySet provides, among the others, two contructors with varargs:
inline explicit KeySet(size_t alloc, va_list ap);
inline explicit KeySet(size_t alloc, ...);
the problem is that on some architectures va_list
is represented as void*
as public type, which makes the two constructor ambiguous when called with alloc
greater than 0 and no additional arguments. In such case, the va_list
version gets used, causing ksVNew
to try to read arguments from a null (or garbage) ap
.
The following patch for src/bindings/cpp/tests/testcpp_ks.cpp
@@ -821,6 +821,18 @@ void test_duplicate()
// ks4.toStream(stdout, 0);
}
+void test_alloc_no_keys()
+{
+ cout << "testing test_alloc_no_keys" << endl;
+
+ KeySet ks (5,
+ KS_END);
+ succeed_if (ks.size() == 5, "size not correct");
+
+ KeySet ks2 (ks);
+ succeed_if (ks2.size() == 5, "size not correct");
+}
+
int main()
{
@@ -844,6 +856,7 @@ int main()
test_ksrelease();
test_lookuppop();
test_duplicate();
+ test_alloc_no_keys();
cout << endl;
cout << "test_key RESULTS: " << nbTest << " test(s) done. " << nbError << " error(s)." << endl;
is enough to trigger the issue on e.g. mips(el) or hppa. Currently this is exposed by the lua and python bindings, since all do:
KeySet(size_t alloc) {
return new kdb::KeySet(alloc, KS_END);
}
In those it can be easily worked around by adding the KS_END
marker a second time (making them really as vararg), but of course it wouldn't fix the issue with the C++ contructors of KeySet.