@@ -157,12 +157,18 @@ set_bits(uint32_t *loc, uint8_t loc_start, uint64_t value, uint8_t value_start,
157157         uint8_t  width )
158158{
159159    assert (loc_start  +  width  <= 32 );
160+     uint32_t  temp_val ;
161+     // Use memcpy to safely read the value, avoiding potential alignment 
162+     // issues and strict aliasing violations. 
163+     memcpy (& temp_val , loc , sizeof (temp_val ));
160164    // Clear the bits we're about to patch: 
161-     * loc  &= ~(((1ULL  << width ) -  1 ) << loc_start );
162-     assert (get_bits (* loc , loc_start , width ) ==  0 );
165+     temp_val  &= ~(((1ULL  << width ) -  1 ) << loc_start );
166+     assert (get_bits (temp_val , loc_start , width ) ==  0 );
163167    // Patch the bits: 
164-     * loc  |= get_bits (value , value_start , width ) << loc_start ;
165-     assert (get_bits (* loc , loc_start , width ) ==  get_bits (value , value_start , width ));
168+     temp_val  |= get_bits (value , value_start , width ) << loc_start ;
169+     assert (get_bits (temp_val , loc_start , width ) ==  get_bits (value , value_start , width ));
170+     // Safely write the modified value back to memory. 
171+     memcpy (loc , & temp_val , sizeof (temp_val ));
166172}
167173
168174// See https://developer.arm.com/documentation/ddi0602/2023-09/Base-Instructions 
@@ -204,30 +210,29 @@ set_bits(uint32_t *loc, uint8_t loc_start, uint64_t value, uint8_t value_start,
204210void 
205211patch_32 (unsigned char   * location , uint64_t  value )
206212{
207-     uint32_t  * loc32  =  (uint32_t  * )location ;
208213    // Check that we're not out of range of 32 unsigned bits: 
209214    assert (value  <  (1ULL  << 32 ));
210-     * loc32  =  (uint32_t )value ;
215+     uint32_t  final_value  =  (uint32_t )value ;
216+     memcpy (location , & final_value , sizeof (final_value ));
211217}
212218
213219// 32-bit relative address. 
214220void 
215221patch_32r (unsigned char   * location , uint64_t  value )
216222{
217-     uint32_t  * loc32  =  (uint32_t  * )location ;
218223    value  -=  (uintptr_t )location ;
219224    // Check that we're not out of range of 32 signed bits: 
220225    assert ((int64_t )value  >= - (1LL  << 31 ));
221226    assert ((int64_t )value  <  (1LL  << 31 ));
222-     * loc32  =  (uint32_t )value ;
227+     uint32_t  final_value  =  (uint32_t )value ;
228+     memcpy (location , & final_value , sizeof (final_value ));
223229}
224230
225231// 64-bit absolute address. 
226232void 
227233patch_64 (unsigned char   * location , uint64_t  value )
228234{
229-     uint64_t  * loc64  =  (uint64_t  * )location ;
230-     * loc64  =  value ;
235+     memcpy (location , & value , sizeof (value ));
231236}
232237
233238// 12-bit low part of an absolute address. Pairs nicely with patch_aarch64_21r 
@@ -410,7 +415,10 @@ patch_x86_64_32rx(unsigned char *location, uint64_t value)
410415{
411416    uint8_t  * loc8  =  (uint8_t  * )location ;
412417    // Try to relax the GOT load into an immediate value: 
413-     uint64_t  relaxed  =  * (uint64_t  * )(value  +  4 ) -  4 ;
418+     uint64_t  relaxed ;
419+     memcpy (& relaxed , (void  * )(value  +  4 ), sizeof (relaxed ));
420+     relaxed  -=  4 ;
421+ 
414422    if  ((int64_t )relaxed  -  (int64_t )location  >= - (1LL  << 31 ) && 
415423        (int64_t )relaxed  -  (int64_t )location  +  1  <  (1LL  << 31 ))
416424    {
0 commit comments