|
| 1 | +Description: Handle unaligned buffers in connect's TYPBLK class |
| 2 | + On MIPS platforms (and probably others) unaligned memory access results in a |
| 3 | + bus error. In the connect storage engine, block data for some data formats is |
| 4 | + stored packed in memory and the TYPBLK class is used to read values from it. |
| 5 | + Since TYPBLK does not have special handling for this packed memory, it can |
| 6 | + quite easily result in unaligned memory accesses. |
| 7 | + . |
| 8 | + The simple way to fix this is to perform all accesses to the main buffer |
| 9 | + through memcpy. With GCC and optimizations turned on, this call to memcpy is |
| 10 | + completely optimized away on architectures where unaligned accesses are ok |
| 11 | + (like x86). |
| 12 | +Author: James Cowgill <jcowgill@debian.org> |
| 13 | +--- |
| 14 | +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ |
| 15 | +--- a/storage/connect/valblk.h |
| 16 | ++++ b/storage/connect/valblk.h |
| 17 | +@@ -139,6 +139,7 @@ class VALBLK : public BLOCK { |
| 18 | + int Prec; // Precision of float values |
| 19 | + }; // end of class VALBLK |
| 20 | + |
| 21 | ++ |
| 22 | + /***********************************************************************/ |
| 23 | + /* Class TYPBLK: represents a block of typed values. */ |
| 24 | + /***********************************************************************/ |
| 25 | +@@ -151,40 +152,40 @@ class TYPBLK : public VALBLK { |
| 26 | + // Implementation |
| 27 | + virtual bool Init(PGLOBAL g, bool check); |
| 28 | + virtual int GetVlen(void) {return sizeof(TYPE);} |
| 29 | +- virtual char GetTinyValue(int n) {return (char)Typp[n];} |
| 30 | +- virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];} |
| 31 | +- virtual short GetShortValue(int n) {return (short)Typp[n];} |
| 32 | +- virtual ushort GetUShortValue(int n) {return (ushort)Typp[n];} |
| 33 | +- virtual int GetIntValue(int n) {return (int)Typp[n];} |
| 34 | +- virtual uint GetUIntValue(int n) {return (uint)Typp[n];} |
| 35 | +- virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];} |
| 36 | +- virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];} |
| 37 | +- virtual double GetFloatValue(int n) {return (double)Typp[n];} |
| 38 | ++ virtual char GetTinyValue(int n) {return (char)UnalignedRead(n);} |
| 39 | ++ virtual uchar GetUTinyValue(int n) {return (uchar)UnalignedRead(n);} |
| 40 | ++ virtual short GetShortValue(int n) {return (short)UnalignedRead(n);} |
| 41 | ++ virtual ushort GetUShortValue(int n) {return (ushort)UnalignedRead(n);} |
| 42 | ++ virtual int GetIntValue(int n) {return (int)UnalignedRead(n);} |
| 43 | ++ virtual uint GetUIntValue(int n) {return (uint)UnalignedRead(n);} |
| 44 | ++ virtual longlong GetBigintValue(int n) {return (longlong)UnalignedRead(n);} |
| 45 | ++ virtual ulonglong GetUBigintValue(int n) {return (ulonglong)UnalignedRead(n);} |
| 46 | ++ virtual double GetFloatValue(int n) {return (double)UnalignedRead(n);} |
| 47 | + virtual char *GetCharString(char *p, int n); |
| 48 | +- virtual void Reset(int n) {Typp[n] = 0;} |
| 49 | ++ virtual void Reset(int n) {UnalignedWrite(n, 0);} |
| 50 | + |
| 51 | + // Methods |
| 52 | + using VALBLK::SetValue; |
| 53 | + virtual void SetValue(PSZ sp, int n); |
| 54 | + virtual void SetValue(char *sp, uint len, int n); |
| 55 | + virtual void SetValue(short sval, int n) |
| 56 | +- {Typp[n] = (TYPE)sval; SetNull(n, false);} |
| 57 | ++ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);} |
| 58 | + virtual void SetValue(ushort sval, int n) |
| 59 | +- {Typp[n] = (TYPE)sval; SetNull(n, false);} |
| 60 | ++ {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);} |
| 61 | + virtual void SetValue(int lval, int n) |
| 62 | +- {Typp[n] = (TYPE)lval; SetNull(n, false);} |
| 63 | ++ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);} |
| 64 | + virtual void SetValue(uint lval, int n) |
| 65 | +- {Typp[n] = (TYPE)lval; SetNull(n, false);} |
| 66 | ++ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);} |
| 67 | + virtual void SetValue(longlong lval, int n) |
| 68 | +- {Typp[n] = (TYPE)lval; SetNull(n, false);} |
| 69 | ++ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);} |
| 70 | + virtual void SetValue(ulonglong lval, int n) |
| 71 | +- {Typp[n] = (TYPE)lval; SetNull(n, false);} |
| 72 | ++ {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);} |
| 73 | + virtual void SetValue(double fval, int n) |
| 74 | +- {Typp[n] = (TYPE)fval; SetNull(n, false);} |
| 75 | ++ {UnalignedWrite(n, (TYPE)fval); SetNull(n, false);} |
| 76 | + virtual void SetValue(char cval, int n) |
| 77 | +- {Typp[n] = (TYPE)cval; SetNull(n, false);} |
| 78 | ++ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);} |
| 79 | + virtual void SetValue(uchar cval, int n) |
| 80 | +- {Typp[n] = (TYPE)cval; SetNull(n, false);} |
| 81 | ++ {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);} |
| 82 | + virtual void SetValue(PVAL valp, int n); |
| 83 | + virtual void SetValue(PVBLK pv, int n1, int n2); |
| 84 | + virtual void SetMin(PVAL valp, int n); |
| 85 | +@@ -206,6 +207,17 @@ class TYPBLK : public VALBLK { |
| 86 | + // Members |
| 87 | + TYPE* const &Typp; |
| 88 | + const char *Fmt; |
| 89 | ++ |
| 90 | ++ // Unaligned access |
| 91 | ++ TYPE UnalignedRead(int n) const { |
| 92 | ++ TYPE result; |
| 93 | ++ memcpy(&result, Typp + n, sizeof(TYPE)); |
| 94 | ++ return result; |
| 95 | ++ } |
| 96 | ++ |
| 97 | ++ void UnalignedWrite(int n, TYPE value) { |
| 98 | ++ memcpy(Typp + n, &value, sizeof(TYPE)); |
| 99 | ++ } |
| 100 | + }; // end of class TYPBLK |
| 101 | + |
| 102 | + /***********************************************************************/ |
| 103 | +--- a/storage/connect/valblk.cpp |
| 104 | ++++ b/storage/connect/valblk.cpp |
| 105 | +@@ -265,14 +265,14 @@ bool TYPBLK<TYPE>::Init(PGLOBAL g, bool |
| 106 | + template <class TYPE> |
| 107 | + char *TYPBLK<TYPE>::GetCharString(char *p, int n) |
| 108 | + { |
| 109 | +- sprintf(p, Fmt, Typp[n]); |
| 110 | ++ sprintf(p, Fmt, UnalignedRead(n)); |
| 111 | + return p; |
| 112 | + } // end of GetCharString |
| 113 | + |
| 114 | + template <> |
| 115 | + char *TYPBLK<double>::GetCharString(char *p, int n) |
| 116 | + { |
| 117 | +- sprintf(p, Fmt, Prec, Typp[n]); |
| 118 | ++ sprintf(p, Fmt, Prec, UnalignedRead(n)); |
| 119 | + return p; |
| 120 | + } // end of GetCharString |
| 121 | + |
| 122 | +@@ -288,7 +288,7 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, i |
| 123 | + ChkTyp(valp); |
| 124 | + |
| 125 | + if (!(b = valp->IsNull())) |
| 126 | +- Typp[n] = GetTypedValue(valp); |
| 127 | ++ UnalignedWrite(n, GetTypedValue(valp)); |
| 128 | + else |
| 129 | + Reset(n); |
| 130 | + |
| 131 | +@@ -350,9 +350,9 @@ void TYPBLK<TYPE>::SetValue(PSZ p, int n |
| 132 | + ulonglong val = CharToNumber(p, strlen(p), maxval, Unsigned, &minus); |
| 133 | + |
| 134 | + if (minus && val < maxval) |
| 135 | +- Typp[n] = (TYPE)(-(signed)val); |
| 136 | ++ UnalignedWrite(n, (TYPE)(-(signed)val)); |
| 137 | + else |
| 138 | +- Typp[n] = (TYPE)val; |
| 139 | ++ UnalignedWrite(n, (TYPE)val); |
| 140 | + |
| 141 | + SetNull(n, false); |
| 142 | + } // end of SetValue |
| 143 | +@@ -395,7 +395,7 @@ void TYPBLK<double>::SetValue(PSZ p, int |
| 144 | + longjmp(g->jumper[g->jump_level], Type); |
| 145 | + } // endif Check |
| 146 | + |
| 147 | +- Typp[n] = atof(p); |
| 148 | ++ UnalignedWrite(n, atof(p)); |
| 149 | + SetNull(n, false); |
| 150 | + } // end of SetValue |
| 151 | + |
| 152 | +@@ -427,7 +427,7 @@ void TYPBLK<TYPE>::SetValue(PVBLK pv, in |
| 153 | + ChkTyp(pv); |
| 154 | + |
| 155 | + if (!(b = pv->IsNull(n2) && Nullable)) |
| 156 | +- Typp[n1] = GetTypedValue(pv, n2); |
| 157 | ++ UnalignedWrite(n1, GetTypedValue(pv, n2)); |
| 158 | + else |
| 159 | + Reset(n1); |
| 160 | + |
| 161 | +@@ -478,10 +478,10 @@ void TYPBLK<TYPE>::SetMin(PVAL valp, int |
| 162 | + { |
| 163 | + CheckParms(valp, n) |
| 164 | + TYPE tval = GetTypedValue(valp); |
| 165 | +- TYPE& tmin = Typp[n]; |
| 166 | ++ TYPE tmin = UnalignedRead(n); |
| 167 | + |
| 168 | + if (tval < tmin) |
| 169 | +- tmin = tval; |
| 170 | ++ UnalignedWrite(n, tval); |
| 171 | + |
| 172 | + } // end of SetMin |
| 173 | + |
| 174 | +@@ -493,10 +493,10 @@ void TYPBLK<TYPE>::SetMax(PVAL valp, int |
| 175 | + { |
| 176 | + CheckParms(valp, n) |
| 177 | + TYPE tval = GetTypedValue(valp); |
| 178 | +- TYPE& tmin = Typp[n]; |
| 179 | ++ TYPE tmin = UnalignedRead(n); |
| 180 | + |
| 181 | + if (tval > tmin) |
| 182 | +- tmin = tval; |
| 183 | ++ UnalignedWrite(n, tval); |
| 184 | + |
| 185 | + } // end of SetMax |
| 186 | + |
| 187 | +@@ -522,7 +522,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, i |
| 188 | + template <class TYPE> |
| 189 | + void TYPBLK<TYPE>::Move(int i, int j) |
| 190 | + { |
| 191 | +- Typp[j] = Typp[i]; |
| 192 | ++ UnalignedWrite(j, UnalignedRead(i)); |
| 193 | + MoveNull(i, j); |
| 194 | + } // end of Move |
| 195 | + |
| 196 | +@@ -536,7 +536,7 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n |
| 197 | + ChkIndx(n); |
| 198 | + ChkTyp(vp); |
| 199 | + #endif // _DEBUG |
| 200 | +- TYPE mlv = Typp[n]; |
| 201 | ++ TYPE mlv = UnalignedRead(n); |
| 202 | + TYPE vlv = GetTypedValue(vp); |
| 203 | + |
| 204 | + return (vlv > mlv) ? 1 : (vlv < mlv) ? (-1) : 0; |
| 205 | +@@ -548,8 +548,8 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n |
| 206 | + template <class TYPE> |
| 207 | + int TYPBLK<TYPE>::CompVal(int i1, int i2) |
| 208 | + { |
| 209 | +- TYPE lv1 = Typp[i1]; |
| 210 | +- TYPE lv2 = Typp[i2]; |
| 211 | ++ TYPE lv1 = UnalignedRead(i1); |
| 212 | ++ TYPE lv2 = UnalignedRead(i2); |
| 213 | + |
| 214 | + return (lv1 > lv2) ? 1 : (lv1 < lv2) ? (-1) : 0; |
| 215 | + } // end of CompVal |
| 216 | +@@ -586,7 +586,7 @@ int TYPBLK<TYPE>::Find(PVAL vp) |
| 217 | + TYPE n = GetTypedValue(vp); |
| 218 | + |
| 219 | + for (i = 0; i < Nval; i++) |
| 220 | +- if (n == Typp[i]) |
| 221 | ++ if (n == UnalignedRead(i)) |
| 222 | + break; |
| 223 | + |
| 224 | + return (i < Nval) ? i : (-1); |
| 225 | +@@ -602,7 +602,7 @@ int TYPBLK<TYPE>::GetMaxLength(void) |
| 226 | + int i, n, m; |
| 227 | + |
| 228 | + for (i = n = 0; i < Nval; i++) { |
| 229 | +- m = sprintf(buf, Fmt, Typp[i]); |
| 230 | ++ m = sprintf(buf, Fmt, UnalignedRead(i)); |
| 231 | + n = MY_MAX(n, m); |
| 232 | + } // endfor i |
| 233 | + |
| 234 | +@@ -1332,7 +1332,7 @@ char *DATBLK::GetCharString(char *p, int |
| 235 | + char *vp; |
| 236 | + |
| 237 | + if (Dvalp) { |
| 238 | +- Dvalp->SetValue(Typp[n]); |
| 239 | ++ Dvalp->SetValue(UnalignedRead(n)); |
| 240 | + vp = Dvalp->GetCharString(p); |
| 241 | + } else |
| 242 | + vp = TYPBLK<int>::GetCharString(p, n); |
| 243 | +@@ -1348,7 +1348,7 @@ void DATBLK::SetValue(PSZ p, int n) |
| 244 | + if (Dvalp) { |
| 245 | + // Decode the string according to format |
| 246 | + Dvalp->SetValue_psz(p); |
| 247 | +- Typp[n] = Dvalp->GetIntValue(); |
| 248 | ++ UnalignedWrite(n, Dvalp->GetIntValue()); |
| 249 | + } else |
| 250 | + TYPBLK<int>::SetValue(p, n); |
| 251 | + |
0 commit comments