I only have 32-bit machines.
Recently I was contacted by someoe who met with grave difficulties when he tried to install my version of the FICS code on his machine (a VPS, actually), running 64-bit CentOS 5.8. The symptoms are basically that after starting the FICS binary, a few error messages are printed to complain that certain files could not be created, after which it exits. In the current directory there are then a number of files with unintelligible names consisting of garbage characters.
I could trace the problem to the use of routines with a variable number of parameters, which are then converted to a va_list, which is passed to vsnprintf, to print the filename into an (allocated) string, which is then used in fopen(). There is a call
vsnprintf(buf, len, "%s", va)
where va is the va_list supposed to contain the filename, and after that buf is filled with garbage.
So it looks like the C-library routine vsnprintf doesn't work, or that somehow the creation of the va_list from the variable arguments of an earlier function call through the standard macro va_start completely messed up, and passes garbage.
I don't know if this is a compiler error, and why I do't have the same problem when I compile on my own Ubuntu 10.04 on a 32-bit machine. Perhaps the FICS code is simply not compatible with a 64-bit compile.
Would it be possible to force a 32-bit compile on a 64-bit system, and run the resulting binary on CentOS? If so, how can that be done?
Q: FICS code and 64-bit (va_list)
Moderators: hgm, Rebel, chrisw
-
- Posts: 27796
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
-
- Posts: 2929
- Joined: Sat Jan 22, 2011 12:42 am
- Location: NL
Re: Q: FICS code and 64-bit (va_list)
You can make a 32 bit executable on a 64 bit system by passing -m32.
Would be better to fix the problem instead of trying to work around it though. My first guess would be that somehow the header file for the function declaration is not included, so the compiler makes an implicit assumption that a point is an int, which is fine if both are 32 bit (on a 32 bit system) but not on many 64 bit systems (where one is 32 bit and one is 64 bit).
Checking whether things compile with -Wall -Werror might help narrow down the problem.
Would be better to fix the problem instead of trying to work around it though. My first guess would be that somehow the header file for the function declaration is not included, so the compiler makes an implicit assumption that a point is an int, which is fine if both are 32 bit (on a 32 bit system) but not on many 64 bit systems (where one is 32 bit and one is 64 bit).
Checking whether things compile with -Wall -Werror might help narrow down the problem.
-
- Posts: 27796
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Q: FICS code and 64-bit (va_list)
Problem is that I normally get thousands of compiler warnings, when doing "make". I will try to see if the -m32 helps, though.
This CentOS is a bit fishy anyway: make install did crash on it not being case sensitive in file names, so that the command "cp [a-z]* ..." also tried to copy the directory CVS, which produced a fatal error.
This CentOS is a bit fishy anyway: make install did crash on it not being case sensitive in file names, so that the command "cp [a-z]* ..." also tried to copy the directory CVS, which produced a fatal error.
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: Q: FICS code and 64-bit (va_list)
Something is broken. Unix has always been case-sensitive. the regular expression "[a-z]*" should NEVER match a file name that does not start with a lowercase alphabetic character, and doesn't on my fedora systems. We did run centos on our lab machines that use unix and I never noticed that being broken, so something is definitely wrong.hgm wrote:Problem is that I normally get thousands of compiler warnings, when doing "make". I will try to see if the -m32 helps, though.
This CentOS is a bit fishy anyway: make install did crash on it not being case sensitive in file names, so that the command "cp [a-z]* ..." also tried to copy the directory CVS, which produced a fatal error.
-
- Posts: 154
- Joined: Thu May 31, 2007 9:05 pm
- Location: Madrid, Spain
Re: Q: FICS code and 64-bit (va_list)
http://pubs.opengroup.org/onlinepubs/00 ... rintf.html
"As these functions invoke the va_arg macro, the value of ap after the return is unspecified."
Maybe you are calling two or more of these functions without calling va_start again.
"As these functions invoke the va_arg macro, the value of ap after the return is unspecified."
Maybe you are calling two or more of these functions without calling va_start again.
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: Q: FICS code and 64-bit (va_list)
I wonder if there is some environment variable one might be able to set to change this default behavior? That could certainly explain part of your difficulty... I've never wanted to disable case sensitivity so have never looked for such a capability.
-
- Posts: 27796
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Q: FICS code and 64-bit (va_list)
Hmm, this could be the case. I lifted the relevant routines out of the code, to show them below. Indeed vsnprintf is called twice, once to find the required size of the buffer it writes in, the second time to do the actual writing. If the first call would destroy ap, the second call would produce garbage.
It is not so obvious how this can be fixed, because the va_start call takes place in the caller, and I have no idea from how many other places m_vasprintf is called. It does not get the info passed that has to be passed to va_start, and it is not even clear it could be passed (because va_start probably takes the address of what you pass to it).
It is not so obvious how this can be fixed, because the va_start call takes place in the caller, and I have no idea from how many other places m_vasprintf is called. It does not get the info passed that has to be passed to va_start, and it is not even clear it could be passed (because va_start probably takes the address of what you pass to it).
Code: Select all
253 /* a vasprintf wrapper */
254 int m_vasprintf(char **strp, const char *fmt, va_list ap)
255 {
256 int n;
257
258 (*strp) = NULL;
259
260 n = vsnprintf(NULL, 0, fmt, ap);
261 if (n == 0) return 0;
262
263 (*strp) = m_malloc(n+1);
264 n = vsnprintf(*strp, n+1, fmt, ap);
265
266 return n;
267 }
#define vasprintf m_vasprintf
1061 /*
1062 like fopen() but uses printf style arguments for the file name
1063 */
1064 FILE *fopen_p(const char *fmt, const char *mode, ...)
1065 {
1066 char *s = NULL;
1067 FILE *f;
1068 va_list ap;
1069 va_start(ap, mode);
1070 vasprintf(&s, fmt, ap);
1071 va_end(ap);
1072 if (!s) return NULL;
1073 if (strstr(s, "..")) {
1074 d_printf("Invalid filename [%s]\n", s);
1075 free(s);
1076 return NULL;
1077 }
1078 f = fopen(s, mode);
1079 free(s);
1080 return f;
1081 }
1082
1083 /*
1084 like fopen() but doesn't allow opening of filenames containing '..'
1085 */
1086 FILE *fopen_s(const char *fname, const char *mode)
1087 {
1088 return fopen_p("%s", mode, fname);
1089 }
#define ADHELP_DIR "./data/admin"
990 afp = fopen_s(ADHELP_DIR "/commands", "w");
991 if (!afp) {
992 d_printf( "CHESSD: Could not write admin commands help file.\n");
993 fclose(fp);
994 return;
995 }
-
- Posts: 33
- Joined: Wed Mar 07, 2012 4:15 pm
- Location: England
Re: Q: FICS code and 64-bit (va_list)
Checking the man page it seems this is your problem:hgm wrote:Hmm, this could be the case. I lifted the relevant routines out of the code, to show them below. Indeed vsnprintf is called twice, once to find the required size of the buffer it writes in, the second time to do the actual writing. If the first call would destroy ap, the second call would produce garbage.
It is not so obvious how this can be fixed, because the va_start call takes place in the caller, and I have no idea from how many other places m_vasprintf is called. It does not get the info passed that has to be passed to va_start, and it is not even clear it could be passed (because va_start probably takes the address of what you pass to it).
Code: Select all
253 /* a vasprintf wrapper */ 254 int m_vasprintf(char **strp, const char *fmt, va_list ap) 255 { 256 int n; 257 258 (*strp) = NULL; 259 260 n = vsnprintf(NULL, 0, fmt, ap); 261 if (n == 0) return 0; 262 263 (*strp) = m_malloc(n+1); 264 n = vsnprintf(*strp, n+1, fmt, ap); 265 266 return n; 267 } #define vasprintf m_vasprintf 1061 /* 1062 like fopen() but uses printf style arguments for the file name 1063 */ 1064 FILE *fopen_p(const char *fmt, const char *mode, ...) 1065 { 1066 char *s = NULL; 1067 FILE *f; 1068 va_list ap; 1069 va_start(ap, mode); 1070 vasprintf(&s, fmt, ap); 1071 va_end(ap); 1072 if (!s) return NULL; 1073 if (strstr(s, "..")) { 1074 d_printf("Invalid filename [%s]\n", s); 1075 free(s); 1076 return NULL; 1077 } 1078 f = fopen(s, mode); 1079 free(s); 1080 return f; 1081 } 1082 1083 /* 1084 like fopen() but doesn't allow opening of filenames containing '..' 1085 */ 1086 FILE *fopen_s(const char *fname, const char *mode) 1087 { 1088 return fopen_p("%s", mode, fname); 1089 } #define ADHELP_DIR "./data/admin" 990 afp = fopen_s(ADHELP_DIR "/commands", "w"); 991 if (!afp) { 992 d_printf( "CHESSD: Could not write admin commands help file.\n"); 993 fclose(fp); 994 return; 995 }
However perhaps you can use the following (defined in C99):If ap is passed to a function that uses va_arg(ap,type) then the value of ap is undefined after the return of that function.
Code: Select all
void va_copy(va_list dest, va_list src);
Last edited by Daniel White on Mon Aug 27, 2012 6:45 pm, edited 1 time in total.
-
- Posts: 1342
- Joined: Wed Mar 08, 2006 9:41 pm
- Location: Morgantown, WV, USA
Re: Q: FICS code and 64-bit (va_list)
Try compiling with gcc-4.4 I had a lot of troubles myself getting it to work with gcc-4.6 after many tries and some code alteration.
Worse case I have a tarball of a 32-bit build (fresh) I could try and send you if you want. I moved that over to my current 64-bit system and haven't had many problems.
-Josh
Worse case I have a tarball of a 32-bit build (fresh) I could try and send you if you want. I moved that over to my current 64-bit system and haven't had many problems.
-Josh
-
- Posts: 27796
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Q: FICS code and 64-bit (va_list)
This was exacly the problem. Thanks for pointing me in the right direction!Pablo Vazquez wrote:"As these functions invoke the va_arg macro, the value of ap after the return is unspecified."
Maybe you are calling two or more of these functions without calling va_start again.
I removed the first call to vsnprintf, and just set the size n+1 to 8000. Now the ICS starts without errors, and I could logon to it.
Could of course be that similar problems exist elsewhere in the code; I will meticulously go through it for uses of va_lists to make sure they are only used once.