@ -1,109 +1,15 @@
Description: Handle unaligned buffers in connect's TYPBLK class
On MIPS platforms (and probably others) unaligned memory access results in a
bus error. In the connect storage engine, block data for some data formats is
stored packed in memory and the TYPBLK class is used to read values from it.
Since TYPBLK does not have special handling for this packed memory, it can
quite easily result in unaligned memory accesses.
.
The simple way to fix this is to perform all accesses to the main buffer
through memcpy. With GCC and optimizations turned on, this call to memcpy is
completely optimized away on architectures where unaligned accesses are ok
(like x86).
Author: James Cowgill <jcowgill@debian.org>
From: Debian MySQL Maintainers <pkg-mysql-maint@lists.alioth.debian.org>
Date: Thu, 10 Aug 2017 20:40:28 +0200
Subject: mips-connect-unaligned
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -139,6 +139,7 @@ class VALBLK : public BLOCK {
int Prec; // Precision of float values
}; // end of class VALBLK
+
/***********************************************************************/
/* Class TYPBLK: represents a block of typed values. */
/***********************************************************************/
@@ -151,40 +152,41 @@ class TYPBLK : public VALBLK {
// Implementation
virtual bool Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(TYPE);}
- virtual char GetTinyValue(int n) {return (char)Typp[n];}
- virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
- virtual short GetShortValue(int n) {return (short)Typp[n];}
- virtual ushort GetUShortValue(int n) {return (ushort)Typp[n];}
- virtual int GetIntValue(int n) {return (int)Typp[n];}
- virtual uint GetUIntValue(int n) {return (uint)Typp[n];}
- virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];}
- virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];}
- virtual double GetFloatValue(int n) {return (double)Typp[n];}
+
+ virtual char GetTinyValue(int n) {return (char)UnalignedRead(n);}
+ virtual uchar GetUTinyValue(int n) {return (uchar)UnalignedRead(n);}
+ virtual short GetShortValue(int n) {return (short)UnalignedRead(n);}
+ virtual ushort GetUShortValue(int n) {return (ushort)UnalignedRead(n);}
+ virtual int GetIntValue(int n) {return (int)UnalignedRead(n);}
+ virtual uint GetUIntValue(int n) {return (uint)UnalignedRead(n);}
+ virtual longlong GetBigintValue(int n) {return (longlong)UnalignedRead(n);}
+ virtual ulonglong GetUBigintValue(int n) {return (ulonglong)UnalignedRead(n);}
+ virtual double GetFloatValue(int n) {return (double)UnalignedRead(n);}
virtual char *GetCharString(char *p, int n);
- virtual void Reset(int n) {Typp[n] = 0;}
+ virtual void Reset(int n) {UnalignedWrite(n, 0);}
// Methods
using VALBLK::SetValue;
virtual void SetValue(PCSZ sp, int n);
virtual void SetValue(const char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
- {Typp[n] = (TYPE)sval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
virtual void SetValue(ushort sval, int n)
- {Typp[n] = (TYPE)sval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
virtual void SetValue(int lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(uint lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(longlong lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(ulonglong lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(double fval, int n)
- {Typp[n] = (TYPE)fval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)fval); SetNull(n, false);}
virtual void SetValue(char cval, int n)
- {Typp[n] = (TYPE)cval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
virtual void SetValue(uchar cval, int n)
- {Typp[n] = (TYPE)cval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetMin(PVAL valp, int n);
@@ -206,6 +208,17 @@ class TYPBLK : public VALBLK {
// Members
TYPE* const &Typp;
const char *Fmt;
+
+ // Unaligned access
+ TYPE UnalignedRead(int n) const {
+ TYPE result;
+ memcpy(&result, Typp + n, sizeof(TYPE));
+ return result;
+ }
+
+ void UnalignedWrite(int n, TYPE value) {
+ memcpy(Typp + n, &value, sizeof(TYPE));
+ }
}; // end of class TYPBLK
/***********************************************************************/
storage/connect/valblk.cpp | 41 ++++++++++++++++++-------------------
storage/connect/valblk.h | 51 +++++++++++++++++++++++++++++-----------------
2 files changed, 52 insertions(+), 40 deletions(-)
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -266,14 +266 ,14 @@ bool TYPBLK<TYPE>::Init(PGLOBAL g, bool
@@ -268,14 +268,14 @@ bool TYPBLK<TYPE>::Init(PGLOBAL g, bool
template <class TYPE>
char *TYPBLK<TYPE>::GetCharString(char *p, int n)
{
@ -120,7 +26,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
return p;
} // end of GetCharString
@@ -28 9,7 +28 9,7 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, i
@@ -291 ,7 +291 ,7 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, i
ChkTyp(valp);
if (!(b = valp->IsNull()))
@ -129,7 +35,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
else
Reset(n);
@@ -351,9 +351 ,9 @@ void TYPBLK<TYPE>::SetValue(PCSZ p, int
@@ -353,9 +353 ,9 @@ void TYPBLK<TYPE>::SetValue(PCSZ p, int
ulonglong val = CharToNumber(p, strlen(p), maxval, Unsigned, &minus);
if (minus && val < maxval)
@ -141,7 +47,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
SetNull(n, false);
} // end of SetValue
@@ -396,7 +396 ,7 @@ void TYPBLK<double>::SetValue(PCSZ p, in
@@ -398,7 +398 ,7 @@ void TYPBLK<double>::SetValue(PCSZ p, in
throw Type;
} // endif Check
@ -150,7 +56,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
SetNull(n, false);
} // end of SetValue
@@ -428,7 +428 ,7 @@ void TYPBLK<TYPE>::SetValue(PVBLK pv, in
@@ -430,7 +430 ,7 @@ void TYPBLK<TYPE>::SetValue(PVBLK pv, in
ChkTyp(pv);
if (!(b = pv->IsNull(n2) && Nullable))
@ -159,7 +65,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
else
Reset(n1);
@@ -479,10 +479 ,10 @@ void TYPBLK<TYPE>::SetMin(PVAL valp, int
@@ -481,10 +481 ,10 @@ void TYPBLK<TYPE>::SetMin(PVAL valp, int
{
CheckParms(valp, n)
TYPE tval = GetTypedValue(valp);
@ -172,7 +78,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
} // end of SetMin
@@ -494,10 +494 ,10 @@ void TYPBLK<TYPE>::SetMax(PVAL valp, int
@@ -496,10 +496 ,10 @@ void TYPBLK<TYPE>::SetMax(PVAL valp, int
{
CheckParms(valp, n)
TYPE tval = GetTypedValue(valp);
@ -185,7 +91,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
} // end of SetMax
@@ -511,8 +511 ,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, i
@@ -513,8 +513 ,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, i
CheckType(pv)
TYPE *lp = ((TYPBLK*)pv)->Typp;
@ -195,7 +101,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
} // end of SetValues
#endif // 0
@@ -523,7 +522 ,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, i
@@ -525,7 +524 ,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, i
template <class TYPE>
void TYPBLK<TYPE>::Move(int i, int j)
{
@ -204,7 +110,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
MoveNull(i, j);
} // end of Move
@@ -537,7 +536 ,7 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n
@@ -539,7 +538 ,7 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n
ChkIndx(n);
ChkTyp(vp);
#endif // _DEBUG
@ -213,7 +119,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
TYPE vlv = GetTypedValue(vp);
return (vlv > mlv) ? 1 : (vlv < mlv) ? (-1) : 0;
@@ -549,8 +548 ,8 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n
@@ -551,8 +550 ,8 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n
template <class TYPE>
int TYPBLK<TYPE>::CompVal(int i1, int i2)
{
@ -224,7 +130,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
return (lv1 > lv2) ? 1 : (lv1 < lv2) ? (-1) : 0;
} // end of CompVal
@@ -587,7 +586 ,7 @@ int TYPBLK<TYPE>::Find(PVAL vp)
@@ -589,7 +588 ,7 @@ int TYPBLK<TYPE>::Find(PVAL vp)
TYPE n = GetTypedValue(vp);
for (i = 0; i < Nval; i++)
@ -233,7 +139,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
break;
return (i < Nval) ? i : (-1);
@@ -603,7 +602 ,7 @@ int TYPBLK<TYPE>::GetMaxLength(void)
@@ -605,7 +604 ,7 @@ int TYPBLK<TYPE>::GetMaxLength(void)
int i, n, m;
for (i = n = 0; i < Nval; i++) {
@ -242,7 +148,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
n = MY_MAX(n, m);
} // endfor i
@@ -1333,7 +1332 ,7 @@ char *DATBLK::GetCharString(char *p, int
@@ -1335,7 +1334 ,7 @@ char *DATBLK::GetCharString(char *p, int
char *vp;
if (Dvalp) {
@ -251,7 +157,7 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
vp = Dvalp->GetCharString(p);
} else
vp = TYPBLK<int>::GetCharString(p, n);
@@ -1349,7 +1348 ,7 @@ void DATBLK::SetValue(PCSZ p, int n)
@@ -1351,7 +1350 ,7 @@ void DATBLK::SetValue(PCSZ p, int n)
if (Dvalp) {
// Decode the string according to format
Dvalp->SetValue_psz(p);
@ -260,3 +166,92 @@ This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
} else
TYPBLK<int>::SetValue(p, n);
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -139,6 +139,7 @@ class VALBLK : public BLOCK {
int Prec; // Precision of float values
}; // end of class VALBLK
+
/***********************************************************************/
/* Class TYPBLK: represents a block of typed values. */
/***********************************************************************/
@@ -151,40 +152,41 @@ class TYPBLK : public VALBLK {
// Implementation
virtual bool Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(TYPE);}
- virtual char GetTinyValue(int n) {return (char)Typp[n];}
- virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
- virtual short GetShortValue(int n) {return (short)Typp[n];}
- virtual ushort GetUShortValue(int n) {return (ushort)Typp[n];}
- virtual int GetIntValue(int n) {return (int)Typp[n];}
- virtual uint GetUIntValue(int n) {return (uint)Typp[n];}
- virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];}
- virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];}
- virtual double GetFloatValue(int n) {return (double)Typp[n];}
+
+ virtual char GetTinyValue(int n) {return (char)UnalignedRead(n);}
+ virtual uchar GetUTinyValue(int n) {return (uchar)UnalignedRead(n);}
+ virtual short GetShortValue(int n) {return (short)UnalignedRead(n);}
+ virtual ushort GetUShortValue(int n) {return (ushort)UnalignedRead(n);}
+ virtual int GetIntValue(int n) {return (int)UnalignedRead(n);}
+ virtual uint GetUIntValue(int n) {return (uint)UnalignedRead(n);}
+ virtual longlong GetBigintValue(int n) {return (longlong)UnalignedRead(n);}
+ virtual ulonglong GetUBigintValue(int n) {return (ulonglong)UnalignedRead(n);}
+ virtual double GetFloatValue(int n) {return (double)UnalignedRead(n);}
virtual char *GetCharString(char *p, int n);
- virtual void Reset(int n) {Typp[n] = 0;}
+ virtual void Reset(int n) {UnalignedWrite(n, 0);}
// Methods
using VALBLK::SetValue;
virtual void SetValue(PCSZ sp, int n);
virtual void SetValue(const char *sp, uint len, int n);
virtual void SetValue(short sval, int n)
- {Typp[n] = (TYPE)sval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
virtual void SetValue(ushort sval, int n)
- {Typp[n] = (TYPE)sval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
virtual void SetValue(int lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(uint lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(longlong lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(ulonglong lval, int n)
- {Typp[n] = (TYPE)lval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
virtual void SetValue(double fval, int n)
- {Typp[n] = (TYPE)fval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)fval); SetNull(n, false);}
virtual void SetValue(char cval, int n)
- {Typp[n] = (TYPE)cval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
virtual void SetValue(uchar cval, int n)
- {Typp[n] = (TYPE)cval; SetNull(n, false);}
+ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
virtual void SetValue(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetMin(PVAL valp, int n);
@@ -206,6 +208,17 @@ class TYPBLK : public VALBLK {
// Members
TYPE* const &Typp;
const char *Fmt;
+
+ // Unaligned access
+ TYPE UnalignedRead(int n) const {
+ TYPE result;
+ memcpy(&result, Typp + n, sizeof(TYPE));
+ return result;
+ }
+
+ void UnalignedWrite(int n, TYPE value) {
+ memcpy(Typp + n, &value, sizeof(TYPE));
+ }
}; // end of class TYPBLK
/***********************************************************************/