summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qstring.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2014-03-18 16:43:36 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-04 19:32:21 +0200
commit964ac38fb0dc84e05606b3abf6f7fcb887a62528 (patch)
tree8156877416e9b603391079cf9c5f29c6c3ad75d2 /src/corelib/tools/qstring.cpp
parent8c0919a2863948ed8705893c574b481dcdc30ff2 (diff)
Don't read before the beginning of the string
The code did discard the the data, so it wasn't affecting the comparison result (tests added anyway), but it could cause crashes if the pointer to the beginning of the data in the first 8 bytes of a page. Change-Id: I618e68de329b65de34ef8c934934c3e631cc6c9f Reported-By: Erik Verbruggen Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
Diffstat (limited to 'src/corelib/tools/qstring.cpp')
-rw-r--r--src/corelib/tools/qstring.cpp16
1 files changed, 11 insertions, 5 deletions
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 7d409708bb..79365b11b1 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -559,11 +559,13 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
}
}
- // we'll read uc[offset..offset+7] (16 bytes) and c[offset-8..offset+7] (16 bytes)
+# ifdef Q_PROCESSOR_X86_64
+ enum { MaxTailLength = 7 };
+ // we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes)
if (uc + offset + 7 < e) {
- // same, but we'll throw away half the data
- __m128i chunk = _mm_loadu_si128((__m128i*)(c + offset - 8));
- __m128i secondHalf = _mm_unpackhi_epi8(chunk, nullmask);
+ // same, but we're using an 8-byte load
+ __m128i chunk = _mm_cvtsi64_si128(*(long long *)(c + offset));
+ __m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask);
__m128i ucdata = _mm_loadu_si128((__m128i*)(uc + offset));
__m128i result = _mm_cmpeq_epi16(secondHalf, ucdata);
@@ -577,6 +579,10 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
// still matched
offset += 8;
}
+# else
+ // 32-bit, we can't do MOVQ to load 8 bytes
+ enum { MaxTailLength = 15 };
+# endif
// reset uc and c
uc += offset;
@@ -584,7 +590,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
# ifdef Q_COMPILER_LAMBDA
const auto &lambda = [=](int i) { return uc[i] - ushort(c[i]); };
- return UnrollTailLoop<7>::exec(e - uc, 0, lambda, lambda);
+ return UnrollTailLoop<MaxTailLength>::exec(e - uc, 0, lambda, lambda);
# endif
#endif