Skip to content

Commit

Permalink
Big-endian fixes: various problems in ilasm (#55349)
Browse files Browse the repository at this point in the history
* Byte-swap property and parameter default values of string type

* Prepare custom attribute blobs in little-endian byte order

* Fix byte order of ELEMENT_TYPE_TYPEDEF typespec blobs

* Fix byte order of VTable blobs
  • Loading branch information
uweigand authored Jul 22, 2021
1 parent 9391b4d commit cc7a8ef
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/coreclr/ilasm/asmman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ void AsmMan::EmitDebuggableAttribute(mdToken tkOwner)
pbsSig->appendInt8(ELEMENT_TYPE_VOID);
pbsSig->append(&bsSigArg);

bsBytes->appendInt32(pAsm->m_dwIncludeDebugInfo);
bsBytes->appendInt32(VAL32(pAsm->m_dwIncludeDebugInfo));
}
bsBytes->appendInt8(0);
bsBytes->appendInt8(0);
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/ilasm/asmparse.y
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,14 @@ ownerType : typeSpec { $$ = $1; }

/* Verbal description of custom attribute initialization blob */
customBlobDescr : customBlobArgs customBlobNVPairs { $$ = $1;
$$->appendInt16(nCustomBlobNVPairs);
$$->appendInt16(VAL16(nCustomBlobNVPairs));
$$->append($2);
nCustomBlobNVPairs = 0; }
;

customBlobArgs : /* EMPTY */ { $$ = new BinStr(); $$->appendInt16(VAL16(0x0001)); }
| customBlobArgs serInit { $$ = $1;
$$->appendFrom($2, (*($2->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); }
AppendFieldToCustomBlob($$,$2); }
| customBlobArgs compControl { $$ = $1; }
;

Expand All @@ -347,7 +347,7 @@ customBlobNVPairs : /* EMPTY */
{ $$ = $1; $$->appendInt8($2);
$$->append($3);
AppendStringWithLength($$,$4);
$$->appendFrom($6, (*($6->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1);
AppendFieldToCustomBlob($$,$6);
nCustomBlobNVPairs++; }
| customBlobNVPairs compControl { $$ = $1; }
;
Expand Down
38 changes: 35 additions & 3 deletions src/coreclr/ilasm/assem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,17 @@ BOOL Assembler::EmitMethod(Method *pMethod)
dwCPlusTypeFlag= (DWORD)*(pMethod->m_pRetValue->ptr());
pValue = (void const *)(pMethod->m_pRetValue->ptr()+1);
cbValue = pMethod->m_pRetValue->length()-1;
if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING) cbValue /= sizeof(WCHAR);
if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING)
{
cbValue /= sizeof(WCHAR);
#if BIGENDIAN
void* pValueTemp = _alloca(cbValue * sizeof(WCHAR));
memcpy(pValueTemp, pValue, cbValue * sizeof(WCHAR));
pValue = pValueTemp;

SwapStringLength((WCHAR*)pValue, cbValue);
#endif
}
}
else
{
Expand Down Expand Up @@ -804,7 +814,17 @@ BOOL Assembler::EmitMethod(Method *pMethod)
dwCPlusTypeFlag= (DWORD)*(pAN->pValue->ptr());
pValue = (void const *)(pAN->pValue->ptr()+1);
cbValue = pAN->pValue->length()-1;
if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING) cbValue /= sizeof(WCHAR);
if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING)
{
cbValue /= sizeof(WCHAR);
#if BIGENDIAN
void* pValueTemp = _alloca(cbValue * sizeof(WCHAR));
memcpy(pValueTemp, pValue, cbValue * sizeof(WCHAR));
pValue = pValueTemp;

SwapStringLength((WCHAR*)pValue, cbValue);
#endif
}
}
else
{
Expand Down Expand Up @@ -986,13 +1006,25 @@ BOOL Assembler::EmitProp(PropDescriptor* pPD)
}
mdOthers[nOthers] = mdMethodDefNil; // like null-terminator

void* pValue = pPD->m_pValue;
#if BIGENDIAN
if (pPD->m_dwCPlusTypeFlag == ELEMENT_TYPE_STRING)
{
void* pValueTemp = _alloca(pPD->m_cbValue * sizeof(WCHAR));
memcpy(pValueTemp, pValue, pPD->m_cbValue * sizeof(WCHAR));
pValue = pValueTemp;

SwapStringLength((WCHAR*)pValue, pPD->m_cbValue);
}
#endif

if(FAILED(m_pEmitter->DefineProperty( pPD->m_tdClass,
wzMemberName,
pPD->m_dwAttr,
pPD->m_pSig,
pPD->m_dwCSig,
pPD->m_dwCPlusTypeFlag,
pPD->m_pValue,
pValue,
pPD->m_cbValue,
mdSet,
mdGet,
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/ilasm/assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,9 @@ class PermissionDecl
m_TypeSpec = type;

m_pbsBlob = new BinStr();
m_pbsBlob->appendInt16(VAL16(1)); // prolog 0x01 0x00
m_pbsBlob->appendInt32((int)action); // 4-byte action
if(pbsPairs) // name-value pairs if any
m_pbsBlob->appendInt16(VAL16(1)); // prolog 0x01 0x00
m_pbsBlob->appendInt32(VAL32((int)action)); // 4-byte action
if(pbsPairs) // name-value pairs if any
{
if(pbsPairs->length() > 2)
m_pbsBlob->appendFrom(pbsPairs,2);
Expand Down
128 changes: 128 additions & 0 deletions src/coreclr/ilasm/grammar_after.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,134 @@ static void AppendStringWithLength(BinStr* pbs, __in __nullterminated char* sz)
}
}

/********************************************************************************/
/* Append a typed field initializer to an untyped custom attribute blob
* Since the result is untyped, we have to byte-swap here on big-endian systems
*/
#ifdef BIGENDIAN
static int ByteSwapCustomBlob(BYTE *ptr, int length, int type, bool isSZArray)
{
BYTE *orig_ptr = ptr;

int nElem = 1;
if (isSZArray)
{
_ASSERTE(length >= 4);
nElem = GET_UNALIGNED_32(ptr);
SET_UNALIGNED_VAL32(ptr, nElem);
if (nElem == 0xffffffff)
nElem = 0;
ptr += 4;
length -= 4;
}

for (int i = 0; i < nElem; i++)
{
switch (type)
{
case ELEMENT_TYPE_BOOLEAN:
case ELEMENT_TYPE_I1:
case ELEMENT_TYPE_U1:
_ASSERTE(length >= 1);
ptr++;
length--;
break;
case ELEMENT_TYPE_CHAR:
case ELEMENT_TYPE_I2:
case ELEMENT_TYPE_U2:
_ASSERTE(length >= 2);
SET_UNALIGNED_VAL16(ptr, GET_UNALIGNED_16(ptr));
ptr += 2;
length -= 2;
break;
case ELEMENT_TYPE_I4:
case ELEMENT_TYPE_U4:
case ELEMENT_TYPE_R4:
_ASSERTE(length >= 4);
SET_UNALIGNED_VAL32(ptr, GET_UNALIGNED_32(ptr));
ptr += 4;
length -= 4;
break;
case ELEMENT_TYPE_I8:
case ELEMENT_TYPE_U8:
case ELEMENT_TYPE_R8:
_ASSERTE(length >= 8);
SET_UNALIGNED_VAL64(ptr, GET_UNALIGNED_64(ptr));
ptr += 8;
length -= 8;
break;
case ELEMENT_TYPE_STRING:
case SERIALIZATION_TYPE_TYPE:
_ASSERTE(length >= 1);
if (*ptr == 0xFF)
{
ptr++;
length--;
}
else
{
int skipped = CorSigUncompressData((PCCOR_SIGNATURE&)ptr);
_ASSERTE(length >= skipped);
ptr += skipped;
length -= skipped;
}
break;
case SERIALIZATION_TYPE_TAGGED_OBJECT:
{
_ASSERTE(length >= 1);
bool objIsSZArray = false;
int objType = *ptr;
ptr++;
length--;
if (type == ELEMENT_TYPE_SZARRAY)
{
_ASSERTE(length >= 1);
objIsSZArray = false;
objType = *ptr;
ptr++;
length--;
}
int skipped = ByteSwapCustomBlob(ptr, length, objType, objIsSZArray);
_ASSERTE(length >= skipped);
ptr += skipped;
length -= skipped;
break;
}
}
}

return ptr - orig_ptr;
}
#endif

static void AppendFieldToCustomBlob(BinStr* pBlob, __in BinStr* pField)
{
pBlob->appendFrom(pField, (*(pField->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1);

#ifdef BIGENDIAN
BYTE *fieldPtr = pField->ptr();
int fieldLength = pField->length();

bool isSZArray = false;
int type = fieldPtr[0];
fieldLength--;
if (type == ELEMENT_TYPE_SZARRAY)
{
isSZArray = true;
type = fieldPtr[1];
fieldLength--;
}

// This may be a bytearray that must not be swapped.
if (type == ELEMENT_TYPE_STRING && !isSZArray)
return;

BYTE *blobPtr = pBlob->ptr() + (pBlob->length() - fieldLength);
ByteSwapCustomBlob(blobPtr, fieldLength, type, isSZArray);
#endif
}


/********************************************************************************/
/* fetch the next token, and return it Also set the yylval.union if the
lexical token also has a value */
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/ilasm/grammar_before.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static char* newStringWDel(__in __nullterminated char* str1, char delimiter, __i
static char* newString(__in __nullterminated const char* str1);
static void corEmitInt(BinStr* buff, unsigned data);
static void AppendStringWithLength(BinStr* pbs, __in __nullterminated char* sz);
static void AppendFieldToCustomBlob(BinStr* pBlob, __in BinStr* pField);
bool bParsingByteArray = FALSE;
int iOpcodeLen = 0;
int iCallConv = 0;
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/ilasm/prebuilt/asmparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2280,7 +2280,7 @@ case 73:
case 74:
#line 334 "asmparse.y"
{ yyval.binstr = yypvt[-1].binstr;
yyval.binstr->appendInt16(nCustomBlobNVPairs);
yyval.binstr->appendInt16(VAL16(nCustomBlobNVPairs));
yyval.binstr->append(yypvt[-0].binstr);
nCustomBlobNVPairs = 0; } break;
case 75:
Expand All @@ -2289,7 +2289,7 @@ case 75:
case 76:
#line 341 "asmparse.y"
{ yyval.binstr = yypvt[-1].binstr;
yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1); } break;
AppendFieldToCustomBlob(yyval.binstr,yypvt[-0].binstr); } break;
case 77:
#line 343 "asmparse.y"
{ yyval.binstr = yypvt[-1].binstr; } break;
Expand All @@ -2301,7 +2301,7 @@ case 79:
{ yyval.binstr = yypvt[-5].binstr; yyval.binstr->appendInt8(yypvt[-4].int32);
yyval.binstr->append(yypvt[-3].binstr);
AppendStringWithLength(yyval.binstr,yypvt[-2].string);
yyval.binstr->appendFrom(yypvt[-0].binstr, (*(yypvt[-0].binstr->ptr()) == ELEMENT_TYPE_SZARRAY) ? 2 : 1);
AppendFieldToCustomBlob(yyval.binstr,yypvt[-0].binstr);
nCustomBlobNVPairs++; } break;
case 80:
#line 353 "asmparse.y"
Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/ilasm/writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1223,12 +1223,12 @@ HRESULT Assembler::CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename)
*pb = ELEMENT_TYPE_TYPEDEF;
memcpy(++pb,pTDD->m_szName,namesize);
pTDD->m_tkTypeSpec = ResolveLocalMemberRef(pTDD->m_tkTypeSpec);
memcpy(pb+namesize,&(pTDD->m_tkTypeSpec),sizeof(mdToken));
SET_UNALIGNED_VAL32(pb+namesize, pTDD->m_tkTypeSpec);
if(TypeFromToken(pTDD->m_tkTypeSpec)==mdtCustomAttribute)
{
CustomDescr* pCA = pTDD->m_pCA;
pbs->appendInt32(pCA->tkType);
pbs->appendInt32(pCA->tkOwner);
pbs->appendInt32(VAL32(pCA->tkType));
pbs->appendInt32(VAL32(pCA->tkOwner));
if(pCA->pBlob) pbs->append(pCA->pBlob);
}
ResolveTypeSpec(pbs);
Expand Down Expand Up @@ -1314,9 +1314,9 @@ HRESULT Assembler::CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename)
{
Method* pMD;
Class* pClass;
m_pVTable->appendInt32(pGlobalLabel->m_GlobalOffset);
m_pVTable->appendInt16(pVTFEntry->m_wCount);
m_pVTable->appendInt16(pVTFEntry->m_wType);
m_pVTable->appendInt32(VAL32(pGlobalLabel->m_GlobalOffset));
m_pVTable->appendInt16(VAL16(pVTFEntry->m_wCount));
m_pVTable->appendInt16(VAL16(pVTFEntry->m_wType));
for(int i=0; (pClass = m_lstClass.PEEK(i)); i++)
{
for(WORD j = 0; (pMD = pClass->m_MethodList.PEEK(j)); j++)
Expand Down

0 comments on commit cc7a8ef

Please sign in to comment.