Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File common/include/byteswap.h clashes with built-in toolchain definition files #5

Closed
JohnnyonFlame opened this issue Jul 3, 2014 · 11 comments
Assignees
Milestone

Comments

@JohnnyonFlame
Copy link
Contributor

Proper solution would be renaming the aforementioned file.
Here's a partial failed scons log for reference.

http://pastebin.com/ZWKabef4

@Matt1360
Copy link
Contributor

Matt1360 commented Jul 3, 2014

What is your build environment?

@JohnnyonFlame
Copy link
Contributor Author

It's an uClibc based toolchain for mips32r2 built using buildroot, used for building binaries for the GCW-Zero console. You can find the toolchain and more info here:

http://www.gcw-zero.com/develop

@Matt1360
Copy link
Contributor

Matt1360 commented Jul 3, 2014

Thanks for the info, I'll check into it quick. The compiler and paths threw me off, I haven't seen this before. Can you try to compile the following and paste me any output (if failure)?

#include <stdint.h>

static uint32_t some_func( const uint32_t& ) { /* No-op */ }
static int32_t some_func( const int32_t& ) { /* No-op */ }

int main()
{
  return 0;
}

You should be able to compile it with mipsel-linux-g++ test.cpp or whatever you save it as. This seems to be an issue with the toolchain, as the code within is valid, although an implicit cast to uint32_t and uint16_t is probably sufficient, not requiring the need for the signed variants - but I'm not sure where, nor how extensively used this code is.

@JohnnyonFlame
Copy link
Contributor Author

Build works as intended, it's definately not a problem in the toolchain. Compiling the header as a separate thing works too.

@Matt1360
Copy link
Contributor

Matt1360 commented Jul 3, 2014

This is valid by the C++ spec. I'll let @vLKp weigh in on this, though.

@mthuurne
Copy link

mthuurne commented Jul 3, 2014

There is a system header named "/usr/include/byteswap.h" in both glibc and uClibc, which "/usr/include/endian.h" tries to include, but it gets "common/include/byteswap.h" instead because it comes first in the include search path. I don't know if this causes the problem Johnny reported, but it would be a good precaution in any case to rename "common/include/byteswap.h" to avoid this name clash. Intercepting system header includes can only lead to trouble.

I agree the code is valid. It also builds fine with the GCW Zero toolchain if built in isolation, so there seems to be a strange interaction between the toolchain and the DXX build that breaks things. I'm one of the maintainers of the GCW Zero toolchain, by the way.

@Matt1360
Copy link
Contributor

Matt1360 commented Jul 3, 2014

This is strange - as it builds on my systems fine. Perhaps there is some inclusion ordering issue. I will review it shortly, and possibly rename byteswap.h to byteutil.h or similar.

@Matt1360
Copy link
Contributor

Matt1360 commented Jul 3, 2014

@JohnnyonFlame Try it now, let me know if it works.

Also, forgive that few minutes where I broke everything because I forgot what branch I was on and merged. Whoops. 👍

@JohnnyonFlame
Copy link
Contributor Author

No biggie. The commit fixes the problem, thanks for your time.

@vLKp
Copy link
Contributor

vLKp commented Jul 3, 2014

This was never intended to intercept system headers, and doing so is work fixing. However, I think the originally reported failure shows a problem in the endian header: the Rebirth header works fine when compiled as C++, but not when compiled as C. Though the compiler was invoked in C++ mode, it appears that endian.h included byteswap.h while inside an extern "C" block, thereby switching to C-style parsing. Generally, you should not have a language mode override open when you include other headers. The included headers may only work with the default parse language.

I can reproduce the reported error if I wrap byteswap.h inside an extern "C" block. Due to limited interaction with the preprocessor, wrapping the header in _#ifdef _cplusplus does not help, since the preprocessor definitions remain set to C++. The only ways to get the right results are either to wrap every C++ header in an explicit extern "C++" to reset the language mode or to assume the caller left the language mode on a sane default.

vLKp pushed a commit that referenced this issue Jul 3, 2014
[Kp: switch to #pragma for byteutil.h]
@mthuurne
Copy link

mthuurne commented Jul 3, 2014

Ah, the error message indeed says "declaration of C function". That explains it: in C there is no name mangling of symbols to support overloading. Thanks for solving the mystery :)

The extern "C" is inserted by the __BEGIN_DECLS macro, defined in /usr/include/sys/cdefs.h and used in /usr/include/sys/types.h, before it includes <bits/types.h>. So it seems that glibc does not follow the convention of wrapping each individual header in extern "C". I don't know if that's a bug or whether they have a different convention to ensure that functions use the right linking conventions. In normal circumstances a system header would never include user code and by the time the preprocessor is done with the system header include the extern "C" block has been properly closed.

vLKp added a commit that referenced this issue Jun 20, 2015
Only respawn when the player presses a fire key/button (primary,
secondary, or flare).  Only clear primary, second, flare, and bomb when
respawning.  This allows dead players to use the automap or change their
camera views.

This is a necessary step to flushing only the firing inputs on respawn,
as requested by Mako88 in
<#104>.  Currently,
inputs are flushed again by the activation of the game window, so
respawn still flushes all inputs.

	#1  0x00005555555cee19 in game_flush_inputs () at similar/main/game.cpp:374
	#2  game_handler (event=...) at similar/main/game.cpp:1114
	#3  0x0000555555576113 in window_send_event (wind=..., event=...) at common/arch/sdl/window.cpp:208
	#4  0x000055555557627b in WINDOW_SEND_EVENT (file=0x5555556dc126 "common/arch/sdl/window.cpp", e=0x5555556dc141 "EVENT_WINDOW_ACTIVATED", line=179, event=..., w=...) at common/include/window.h:111
	#5  window_set_visible (w=..., visible=visible@entry=1) at common/arch/sdl/window.cpp:179
	#6  0x00005555555e90f5 in window_set_visible (visible=1, wind=<optimized out>) at common/include/window.h:90
	#7  DoPlayerDead () at similar/main/gameseq.cpp:1479
	#8  0x000055555563ed65 in dead_player_frame () at similar/main/object.cpp:1486
	#9  0x00005555555cf4df in GameProcessFrame () at similar/main/game.cpp:1329
	#10 game_handler (event=...) at similar/main/game.cpp:1157
@vLKp vLKp self-assigned this Sep 22, 2015
@vLKp vLKp added this to the 0.60 milestone Sep 22, 2015
vLKp added a commit that referenced this issue Feb 1, 2020
Returning from a secret level clears the player's `hostages_on_board` to
0 as part of initializing a "new" ship, but this is not desirable
behavior.  Copy the counter out before and back afterward.

    ```
    Thread 1 "d2x-rebirth-edi" hit Hardware watchpoint 1: -location d2x::LevelUniqueObjectState.Objects._M_elems[0].ctype.player_info.mission.hostages_on_board

    Old value = 5 '\005'
    New value = 0 '\000'

    #0  d2x::init_player_stats_ship (GameTime64=<optimized out>, plrobj=...) at similar/main/gameseq.cpp:613
    #1  d2x::init_player_stats_level (secret_flag=d2x::secret_restore::survived, plrobj=..., plr=...) at similar/main/gameseq.cpp:615
    #2  d2x::StartNewLevelSub (level_num=level_num@entry=3, page_in_textures=page_in_textures@entry=1, secret_flag=secret_flag@entry=d2x::secret_restore::survived) at similar/main/gameseq.cpp:1901
    #3  d2x::state_restore_all_sub (LevelSharedDestructibleLightState=..., secret=d2x::secret_restore::survived, filename=<optimized out>) at similar/main/state.cpp:1670
    #4  d2x::state_restore_all (in_game=in_game@entry=1, secret=secret@entry=d2x::secret_restore::survived, filename_override=<optimized out>, blind=blind@entry=dcx::blind_save::no) at similar/main/state.cpp:1490
    #5  d2x::ExitSecretLevel ()
    ```

Reported-by: teratorn <#495>
plomari pushed a commit to plomari/dxx that referenced this issue Jun 11, 2021
I got this in Fight For Your Life, level 19:

main/wall.c:314(wall_open_door): Assert(w->type == WALL_DOOR)
=================================================================
==3862770==ERROR: AddressSanitizer: global-buffer-overflow on address
0x562dee57e448 at pc 0x562decd2169c bp 0x7ffc5d624400 sp 0x7ffc5d6243f8
READ of size 2 at 0x562dee57e448 thread T0
    #0 0x562decd2169b in find_connect_side main/gameseg.c:85
    dxx-rebirth#1 0x562ded061683 in wall_open_door main/wall.c:367
    dxx-rebirth#2 0x562decc10ccf in collide_robot_and_wall main/collide.c:115
    dxx-rebirth#3 0x562decc3d5a1 in collide_object_with_wall main/collide.c:2598
    dxx-rebirth#4 0x562decfa4ef1 in do_physics_sim main/physics.c:529
    dxx-rebirth#5 0x562decf8f1c5 in object_move_one main/object.c:1727
    dxx-rebirth#6 0x562decf92000 in object_move_all main/object.c:1858
    dxx-rebirth#7 0x562deccc8090 in GameProcessFrame main/game.c:1126
    dxx-rebirth#8 0x562deccc5ea9 in game_handler main/game.c:904
    dxx-rebirth#9 0x562decb5c486 in window_send_event arch/sdl/window.c:230
    dxx-rebirth#10 0x562decb4ed2c in event_process arch/sdl/event.c:184
    dxx-rebirth#11 0x562decb4efa2 in window_run_event_loop arch/sdl/event.c:206
    dxx-rebirth#12 0x562decdfbe8d in main main/inferno.c:341
    dxx-rebirth#13 0x7f7ec936ed09 in __libc_start_main ../csu/libc-start.c:308
(/mnt/big/doh/sandgrube/dxx-rebirth/d2x-rebirth-gl+0x7bcd69)

0x562dee57e448 is located 4 bytes to the right of global variable
'd_tick_step' defined in 'main/mglobal.c:38:5' (0x562dee57e440) of size
4
0x562dee57e448 is located 56 bytes to the left of global variable
'Segments' defined in 'main/mglobal.c:40:9' (0x562dee57e480) of size
10720000
SUMMARY: AddressSanitizer: global-buffer-overflow main/gameseg.c:85 in
find_connect_side
Shadow bytes around the buggy address:
  0x0ac63dca7c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7c50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7c70: 00 00 00 00 f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9
=>0x0ac63dca7c80: 04 f9 f9 f9 f9 f9 f9 f9 04[f9]f9 f9 f9 f9 f9 f9
  0x0ac63dca7c90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7ca0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7cb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7cc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ac63dca7cd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==3862770==ABORTING

Possibly unreproducable. Judging from collide_robot_and_wall, maybe it's
a case where a wall was marked as needing a key, but there's no door?
Unknown. Try to avoid this by returning if it makes no sense.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants