Robert Szeleney
2006-Jun-27 12:41 UTC
[Samba] iconv.c / static charset prototype/assembler bug?
Hi! I think there is a little bug in the current samba release (3.0.22). Take a look at cp850.c at the last line and you will see following definition: SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CP850) Using the macros from charset.c, the preprocessor expands this to: NTSTATUS charset_CP850_init(void) \ { \ return smb_register_charset(&CP850_functions); \ } \ NTSTATUS is defined in nt_status.h as follows: typedef struct {uint32 v;} NTSTATUS; #define NT_STATUS(x) ((NTSTATUS) { x }) #define NT_STATUS_V(x) ((x).v) Ok, when cp850/cp437 is compiled as static, config.h has following macro: #define static_init_charset { charset_CP850_init(); charset_CP437_init();} This static_init_charset macro gets called in iconv.c. But at this point in the file there is no function prototype for charset_CP850_init and charset_CP437_init. Thus gcc, doesn't know that it has to reserve space on the stack for this 4 byte return value which actually gets returned AND pushed to the stack by charset_CP850_init. After adding following prototype to config.h, everything works as expected: NT_STATUS charset_CP850_init(void); You may look at this disassembly which shows whats going wrong exactely: iconv.c: smb_iconv_open(): (With the NT_STATUS charset_CP850_init(void); prototype:) 807c173: 85 c0 test %eax,%eax 807c175: 75 e9 jne 807c160 <smb_iconv_open+0x3a> 807c177: 8d 45 ec lea 0xffffffec(%ebp),%eax 807c17a: 83 ec 0c sub $0xc,%esp 807c17d: 50 push %eax // here gcc reserves space on the stack 807c17e: e8 b9 96 00 00 call 808583c <charset_CP850_init> 807c183: 83 c4 0c add $0xc,%esp 807c186: e8 7d 98 00 00 call 8085a08 <charset_CP437_init> iconv.c: smb_iconv_open(): (Without the NT_STATUS charset_CP850_init(void); prototype:) 807c173: 85 c0 test %eax,%eax 807c175: 75 e9 jne 807c160 <smb_iconv_open+0x3a> 807c177: e8 b8 96 00 00 call 8085834 <charset_CP850_init> // no space reserved 807c17c: e8 7f 98 00 00 call 8085a00 <charset_CP437_init> cp850.c : charset_CP850_init 808583c: 55 push %ebp 808583d: 89 e5 mov %esp,%ebp 808583f: 56 push %esi 8085840: 53 push %ebx 8085841: 83 ec 18 sub $0x18,%esp 8085844: e8 00 00 00 00 call 8085849 <charset_CP850_init+0xd> 8085849: 5b pop %ebx 808584a: 81 c3 8f 1a 03 00 add $0x31a8f,%ebx 8085850: 8b 75 08 mov 0x8(%ebp),%esi // read NT_STATUS 8085853: 8d 55 f4 lea 0xfffffff4(%ebp),%edx 8085856: 8d 83 ac 60 00 00 lea 0x60ac(%ebx),%eax 808585c: 50 push %eax 808585d: 52 push %edx 808585e: e8 73 67 ff ff call 807bfd6 <smb_register_charset> 8085863: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 8085866: 89 06 mov %eax,(%esi) // write NT_STATUS 8085868: 89 f0 mov %esi,%eax 808586a: 8d 65 f8 lea 0xfffffff8(%ebp),%esp 808586d: 5b pop %ebx 808586e: 5e pop %esi 808586f: 5d pop %ebp 8085870: c2 04 00 ret $0x4 8085873: 90 nop As you can see, 8085866: 89 06 mov %eax,(%esi) // write NT_STATUS tries to write the error code to the address pushed on the stack before, which actually never happened when the prototype is missing. Btw, this is compiled with GCC 4.1.1 / ELF / PIC May I be wrong here? Do you need any additional information? Thanks! Robert! http://www.skyos.org
Jeremy Allison
2006-Jun-27 23:56 UTC
[Samba] iconv.c / static charset prototype/assembler bug?
On Tue, Jun 27, 2006 at 02:25:28PM +0200, Robert Szeleney wrote:> Hi! > > I think there is a little bug in the current samba release (3.0.22). > > Take a look at cp850.c at the last line and you will see following > definition: > > SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CP850) > > Using the macros from charset.c, the preprocessor expands this to: > > NTSTATUS charset_CP850_init(void) \ > { \ > return smb_register_charset(&CP850_functions); \ > } \ > > NTSTATUS is defined in nt_status.h as follows: > > typedef struct {uint32 v;} NTSTATUS; > #define NT_STATUS(x) ((NTSTATUS) { x }) > #define NT_STATUS_V(x) ((x).v) > > > Ok, when cp850/cp437 is compiled as static, config.h has following macro: > #define static_init_charset { charset_CP850_init(); > charset_CP437_init();} > > This static_init_charset macro gets called in iconv.c. But at this point > in the file there is no function prototype for charset_CP850_init and > charset_CP437_init. Thus gcc, doesn't know that it has to reserve space on > the stack for this 4 byte return value which actually gets returned AND > pushed to the stack by charset_CP850_init.Ok, I've looked into this in the current SAMBA_3_0 codebase (the code that's in 3.0.23RC3) and this problem shouldn't happen. When you configure with : ./configure.developer --with-static-modules=charset_CP850 You get : /* Decl of Static init functions */ #define static_decl_charset extern NTSTATUS charset_CP850_init(void); followed by : #define static_init_charset { charset_CP850_init();} defined in include/config.h in lib/iconv.c we have : static_decl_charset; at the top of the file (after #include "includes.h") followed by : static void lazy_initialize_iconv(void) { static BOOL initialized; int i; if (!initialized) { initialized = True; for(i = 0; builtin_functions[i].name; i++) smb_register_charset(&builtin_functions[i]); static_init_charset; } } - this should cause the correct declaration and definition to be used. Follow up this email if you think I'm incorrect on this but I don't think it's a problem in 3.0.23 RC3. Jeremy.
Reasonably Related Threads
- Fwd: Re: Possible Samba Memory Leak
- Samba unable to connect to ldap
- Solaris username character limit issues.
- 2nd try: Lots of RPC-related compile errors (conflicting types, too many arguments, ...) trying to update Samba from 3.5 to 4.6
- How to tell if option "with-acl-support" is compiledin Solaris smbd?