-
-
Notifications
You must be signed in to change notification settings - Fork 56.5k
Trivially copyable types breaking ABI compatiblity #20878
Copy link
Copy link
Closed
Description
System information (version)
- OpenCV => 4.5.4
- Operating System / Platform => Arch Linux
- Compiler => GCC 11.1.0
Detailed description
eab2b9d made a few small classes trivially copyable. However, it changes how theses types are passed as function arguments, thus breaking binary compatibility and causing crashes of code built against earlier versions of opencv headers.
Steps to reproduce
#include <opencv2/core.hpp>
void foo() {
cv::Size size(1, 2);
cv::Mat mat(size, 3);
}Just compile the above code against opencv 4.5.3 and 4.5.4 and check disassembler output.
g++ -c -o foo.o foo.cpp -I /usr/include/opencv4
objdump --demangle -rd foo.oopencv 4.5.3
0000000000000000 <foo()>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 c4 80 add $0xffffffffffffff80,%rsp
8: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
f: 00 00
11: 48 89 45 f8 mov %rax,-0x8(%rbp)
15: 31 c0 xor %eax,%eax
17: 48 8d 45 80 lea -0x80(%rbp),%rax
1b: ba 02 00 00 00 mov $0x2,%edx
20: be 01 00 00 00 mov $0x1,%esi
25: 48 89 c7 mov %rax,%rdi
28: e8 00 00 00 00 call 2d <foo()+0x2d>
29: R_X86_64_PLT32 cv::Size_<int>::Size_(int, int)-0x4
2d: 48 8d 55 80 lea -0x80(%rbp),%rdx
31: 48 8d 45 88 lea -0x78(%rbp),%rax
35: 48 89 d6 mov %rdx,%rsi
38: 48 89 c7 mov %rax,%rdi
3b: e8 00 00 00 00 call 40 <foo()+0x40>
3c: R_X86_64_PLT32 cv::Size_<int>::Size_(cv::Size_<int> const&)-0x4
40: 48 8d 4d 88 lea -0x78(%rbp),%rcx
44: 48 8d 45 90 lea -0x70(%rbp),%rax
48: ba 03 00 00 00 mov $0x3,%edx
4d: 48 89 ce mov %rcx,%rsi
50: 48 89 c7 mov %rax,%rdi
53: e8 00 00 00 00 call 58 <foo()+0x58>
54: R_X86_64_PLT32 cv::Mat::Mat(cv::Size_<int>, int)-0x4
58: 48 8d 45 90 lea -0x70(%rbp),%rax
5c: 48 89 c7 mov %rax,%rdi
5f: e8 00 00 00 00 call 64 <foo()+0x64>
60: R_X86_64_PLT32 cv::Mat::~Mat()-0x4
64: 48 8b 45 f8 mov -0x8(%rbp),%rax
68: 64 48 2b 04 25 28 00 sub %fs:0x28,%rax
6f: 00 00
71: 74 05 je 78 <foo()+0x78>
73: e8 00 00 00 00 call 78 <foo()+0x78>
74: R_X86_64_PLT32 __stack_chk_fail-0x4
78: c9 leave
79: c3 ret
After calling copy constructor of Size_, address of the object is taken (lea -0x78(%rbp),%rcx) and passed to constructor of Mat (mov %rcx,%rsi).
opencv 4.5.4
0000000000000000 <foo()>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 c4 80 add $0xffffffffffffff80,%rsp
8: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
f: 00 00
11: 48 89 45 f8 mov %rax,-0x8(%rbp)
15: 31 c0 xor %eax,%eax
17: 48 8d 45 88 lea -0x78(%rbp),%rax
1b: ba 02 00 00 00 mov $0x2,%edx
20: be 01 00 00 00 mov $0x1,%esi
25: 48 89 c7 mov %rax,%rdi
28: e8 00 00 00 00 call 2d <foo()+0x2d>
29: R_X86_64_PLT32 cv::Size_<int>::Size_(int, int)-0x4
2d: 48 8b 4d 88 mov -0x78(%rbp),%rcx
31: 48 8d 45 90 lea -0x70(%rbp),%rax
35: ba 03 00 00 00 mov $0x3,%edx
3a: 48 89 ce mov %rcx,%rsi
3d: 48 89 c7 mov %rax,%rdi
40: e8 00 00 00 00 call 45 <foo()+0x45>
41: R_X86_64_PLT32 cv::Mat::Mat(cv::Size_<int>, int)-0x4
45: 48 8d 45 90 lea -0x70(%rbp),%rax
49: 48 89 c7 mov %rax,%rdi
4c: e8 00 00 00 00 call 51 <foo()+0x51>
4d: R_X86_64_PLT32 cv::Mat::~Mat()-0x4
51: 48 8b 45 f8 mov -0x8(%rbp),%rax
55: 64 48 2b 04 25 28 00 sub %fs:0x28,%rax
5c: 00 00
5e: 74 05 je 65 <foo()+0x65>
60: e8 00 00 00 00 call 65 <foo()+0x65>
61: R_X86_64_PLT32 __stack_chk_fail-0x4
65: c9 leave
66: c3 ret
After calling constructor of Size_, content of the object is copied mov -0x78(%rbp),%rcx (as two ints in the object just fits in a 64-bit register) and passed to constructor of Mat.
Issue submission checklist
- I report the issue, it's not a question
- I checked the problem with documentation, FAQ, open issues,
forum.opencv.org, Stack Overflow, etc and have not found solution - I updated to latest OpenCV version and the issue is still there
- There is reproducer code and related data files: videos, images, onnx, etc
Reactions are currently unavailable