QSA-interest Archive, February 2006
QSA 1.2.0: Assert failure w/ large Enum values
Message 1 in thread
Hey all,
I think I found another bug with QSA 1.2.0. I haven't spend much
time yet trying to see if there's an easy fix.
Here is the bug: if an object has an enum with a large (larger than
2<<16) value, trying to access than enum causes QSA to abort on an
assert failure. For example,
For example, consider this class:
class TestClass: public QObject {
Q_OBJECT
Q_ENUMS(Crash);
public:
TestClass();
virtual ~TestClass();
enum Crash { BadValue = 0x02000000 };
};
If there is an instance of that class in the script environment, and
the script tries to use the "BadValue" enum value, QSA aborts with
this error:
ASSERT: "member_index < (2<<16)" in file ../kernel/quickobjects.cpp,
line 88
It seems that QSA checks the enum value (0x02000000 in this case),
and if it is bigger than a 16-bit value (as this one is), it fails
this assertion.
For now, I will rewrite my code to use smaller enum values, but it
would be nice if this wasn't necessary. (For flag-type enums where
each value sets a different bit, it is quite easy to have values
larger than 16-bit.)
Regards,
Joel Nordell
Software Engineer
ONEAC Corp.
Message 2 in thread
Joel Nordell wrote:
> Hey all,
>
> I think I found another bug with QSA 1.2.0. I haven't spend much time
> yet trying to see if there's an easy fix.
>
> Here is the bug: if an object has an enum with a large (larger than
> 2<<16) value, trying to access than enum causes QSA to abort on an
> assert failure. For example,
Hi Joel,
This is a bug, and the attahed patch should fix the problem.
-
Gunnar
==== src/kernel/quickobjects.cpp - src\kernel\quickobjects.cpp ====
==== src/kernel/quickobjects.cpp - src\kernel\quickobjects.cpp ====
@@ -53,28 +53,39 @@
using namespace QS;
-// static QSObject uObjectToQS(QuickInterpreter *ip,
-// QUObject *o, const void *extra=0);
-// static bool qsToUObject( QUObject *o,
-// const QSObject &v,
-// QUType *t,
-// const void *extra,
-// Q3PtrList<qs_ptr_ref> *allocs,
-// qs_method_info *);
+// Returns a uint that has the \a x lowest bit set.
+static inline uint low_bits(int x) {
+ return 0xffffffff >> (32 - x);
+}
+
+const int OBJECT_INDEX_SIZE = 5;
+const int MEMBER_TYPE_SIZE = 3;
+const int MEMBER_INDEX_SIZE = 24;
static inline uint qsa_encode_member_index(QSWrapperClass::MemberType member_type, uint object_index, uint member_index)
{
// make sure we have enough space...
- Q_ASSERT(object_index < 256);
- Q_ASSERT(member_type < 256);
- Q_ASSERT(member_index < (2<<16));
+ Q_ASSERT(object_index < (1<<OBJECT_INDEX_SIZE));
+ Q_ASSERT(member_type < (1<<MEMBER_TYPE_SIZE));
+ Q_ASSERT(member_index < (1<<MEMBER_INDEX_SIZE));
+
+ return (object_index << (32 - OBJECT_INDEX_SIZE))
+ | (member_type << (32 - MEMBER_TYPE_SIZE - OBJECT_INDEX_SIZE))
+ | member_index;
+}
+
+static inline uint qsa_decode_index_object(uint index) {
+ return index >> (32 - OBJECT_INDEX_SIZE);
+}
+
+static inline uint qsa_decode_index_type(uint index) {
+ return (index >> (32 - OBJECT_INDEX_SIZE - MEMBER_TYPE_SIZE)) & low_bits(MEMBER_TYPE_SIZE);
+}
- return (object_index << 24) | (member_type << 16) | member_index;
+static inline uint qsa_decode_index_member(uint index) {
+ return index & low_bits(MEMBER_INDEX_SIZE);
}
-static inline uint qsa_decode_index_object(uint index) { return index >> 24; }
-static inline uint qsa_decode_index_type(uint index) { return (index >> 16) & 0xff; }
-static inline uint qsa_decode_index_member(uint index) { return index & 0x0000ffff; }
QSObject qsa_execute_slot(QSEnv *env, QObject *qobject, const QList<int> &slot_indexes);
@@ -282,7 +293,7 @@
// enums
{
- int value = -1;
+ uint value = 0;
bool ok = false;
for (int search_idx = meta_object->enumeratorCount() - 1;
search_idx >= 0 && !ok;
@@ -291,7 +302,7 @@
for (int key_idx=0; key_idx<metaEnum.keyCount() && !ok; ++key_idx) {
if (qstrcmp(metaEnum.key(key_idx), member_name) == 0) {
ok = true;
- value = metaEnum.value(key_idx);
+ value = (key_idx & low_bits(14)) | ((search_idx & low_bits(10)) << 14);
}
}
}
@@ -343,7 +354,13 @@
break;
case EnumType:
- return env()->createNumber(member_index);
+ {
+ int search_idx = (member_index >> 14) & low_bits(10);
+ int key_idx = (member_index & low_bits(14));
+
+ QMetaEnum metaEnum = meta_object->enumerator(search_idx);
+ return env()->createNumber(metaEnum.value(key_idx));
+ }
break;
case ObjectType: