Fix SortArray crashing with bad comparison functions
This commit is contained in:
parent
4e4702e386
commit
9d27bd3c3b
2 changed files with 31 additions and 5 deletions
|
@ -259,7 +259,7 @@ Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
|
||||||
|
|
||||||
ERR_FAIL_NULL_V(p_obj, *this);
|
ERR_FAIL_NULL_V(p_obj, *this);
|
||||||
|
|
||||||
SortArray<Variant, _ArrayVariantSortCustom> avs;
|
SortArray<Variant, _ArrayVariantSortCustom, true> avs;
|
||||||
avs.compare.obj = p_obj;
|
avs.compare.obj = p_obj;
|
||||||
avs.compare.func = p_function;
|
avs.compare.func = p_function;
|
||||||
avs.sort(_p->array.ptrw(), _p->array.size());
|
avs.sort(_p->array.ptrw(), _p->array.size());
|
||||||
|
|
34
core/sort.h
34
core/sort.h
|
@ -36,13 +36,25 @@
|
||||||
@author ,,, <red@lunatea>
|
@author ,,, <red@lunatea>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define ERR_BAD_COMPARE(cond) \
|
||||||
|
if (unlikely(cond)) { \
|
||||||
|
ERR_PRINT("bad comparison function; sorting will be broken"); \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct _DefaultComparator {
|
struct _DefaultComparator {
|
||||||
|
|
||||||
inline bool operator()(const T &a, const T &b) const { return (a < b); }
|
_FORCE_INLINE_ bool operator()(const T &a, const T &b) const { return (a < b); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class Comparator = _DefaultComparator<T> >
|
#ifdef DEBUG_ENABLED
|
||||||
|
#define SORT_ARRAY_VALIDATE_ENABLED true
|
||||||
|
#else
|
||||||
|
#define SORT_ARRAY_VALIDATE_ENABLED false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
|
||||||
class SortArray {
|
class SortArray {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -164,12 +176,23 @@ public:
|
||||||
|
|
||||||
inline int partitioner(int p_first, int p_last, T p_pivot, T *p_array) const {
|
inline int partitioner(int p_first, int p_last, T p_pivot, T *p_array) const {
|
||||||
|
|
||||||
|
const int unmodified_first = p_first;
|
||||||
|
const int unmodified_last = p_last;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
while (compare(p_array[p_first], p_pivot))
|
while (compare(p_array[p_first], p_pivot)) {
|
||||||
|
if (Validate) {
|
||||||
|
ERR_BAD_COMPARE(p_first == unmodified_last - 1)
|
||||||
|
}
|
||||||
p_first++;
|
p_first++;
|
||||||
|
}
|
||||||
p_last--;
|
p_last--;
|
||||||
while (compare(p_pivot, p_array[p_last]))
|
while (compare(p_pivot, p_array[p_last])) {
|
||||||
|
if (Validate) {
|
||||||
|
ERR_BAD_COMPARE(p_last == unmodified_first)
|
||||||
|
}
|
||||||
p_last--;
|
p_last--;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(p_first < p_last))
|
if (!(p_first < p_last))
|
||||||
return p_first;
|
return p_first;
|
||||||
|
@ -238,6 +261,9 @@ public:
|
||||||
|
|
||||||
int next = p_last - 1;
|
int next = p_last - 1;
|
||||||
while (compare(p_value, p_array[next])) {
|
while (compare(p_value, p_array[next])) {
|
||||||
|
if (Validate) {
|
||||||
|
ERR_BAD_COMPARE(next == 0)
|
||||||
|
}
|
||||||
p_array[p_last] = p_array[next];
|
p_array[p_last] = p_array[next];
|
||||||
p_last = next;
|
p_last = next;
|
||||||
next--;
|
next--;
|
||||||
|
|
Loading…
Reference in a new issue