Opened 20 years ago
Closed 16 years ago
#738 closed defect (fixed)
Mapserver 4.2.0 Template Problem
Reported by: | Owned by: | sdlime | |
---|---|---|---|
Priority: | normal | Milestone: | |
Component: | MapServer CGI | Version: | 4.2 |
Severity: | blocker | Keywords: | |
Cc: | m.spring@… |
Description (last modified by )
The processLine function in maptemplate.c does not replace templates like [layers] correctly. This is unique to the Linux version. There are no problems with the Windows version. If "...&layers=layer1+layer2+layer3..." is passed to mapserver via the URL, all layers are displayed, but only the last (layer3) is returned to the [layers] variable in the template. The same happens with [layer_esc], [toggle_layers] etc. Possible cause and solution: The snprintf function used to replace [layers] with the actual values does not work the way it should (on linux systems). I replaced snprintf by strcat, which works perfectly for me, e.g. -- strcpy(repstr, ""); // Layer list for a "POST" request -- for(i=0;i<msObj->NumLayers;i++) -- snprintf(repstr, PROCESSLINE_BUFLEN, "%s%s ", repstr, msObj->Layers[i]); ++ strcpy(repstr, ""); // Layer list for a "POST" request ++ for(i=0;i<msObj->NumLayers;i++) { ++ strcat(repstr, msObj->Layers[i]); ++ strcat(repstr, " "); // Layer list for a "POST" request ++ } This fixes the problem on my system.
Change History (18)
comment:2 by , 20 years ago
Cc: | added |
---|
template variable [layers] contains only last selected layer instead of all layers. Reason is a snprintf error in maptemplate.c
comment:3 by , 20 years ago
Using snprintf() this way is definitely not a good idea: it's a waste of CPU cycles to copy the buffer over itself and as we see here it can lead to problems. I see three instances of this problem in maptemplate.c To prevent a buffer overflow, we could change the loop to something like the following. I could take care of it if you want, just let me know: char *repstrptr; ... repstr[0] = '\0'; // Layer list for a "POST" request repstrptr = repstr; for(i=0;i<msObj->NumLayers;i++) { int itemlen; itemlen = strlen(msObj->Layers[i]); if ((repstrptr - repstr)+itemlen+1 >= PROCESSLINE_BUFLEN) break; // Prevent buffer overflow! if (repstrptr != repstr) strcpy(repstrptr++, " "); // Insert delimiter unless this is first item strcpy(repstrptr, msObj->Layers[i]); repstrptr += itemlen; }
comment:4 by , 20 years ago
Is this just a snprintf problem or an issue with sprintf as well? Someone changed all references from sprintf to snprintf all over the MapServer source. Maybe we need low-level function, a smarter strcat, instead. Something analogous to strcatalloc but for static buffers.
comment:5 by , 20 years ago
Dan: Are you familiar with the function strlcat? Seems to do what we want. I'm thinking it's not real common though, only available on BSDish systems. I'm thinking your code could simply morph into a msStrlcat. I'll try that tonite... Steve
comment:6 by , 20 years ago
In absence of strlcat how about simply: for(i=0;i<msObj->NumLayers;i++) { strncat(repstr, msObj->Layers[i], sizeof(repstr) - strlen(msObj->Layers[i]) - 1); strncat(repstr, " ", sizeof(repstr) - 2); }
comment:7 by , 20 years ago
Ouch! Mid-air collision! I don't think using strncat as you suggest would work since the size argument to strncat is the number of chars from the source string to copy: it has nothing to do with the size of the target buffer. However using strlcat I think we could turn the loop into: repstr[0] = '\0'; // Layer list for a "POST" request for(i=0;i<msObj->NumLayers;i++) { if (i>0) strlcat(repstr, " ", sizeof(repstr)); strlcat(repstr, msObj->Layers[i], sizeof(repstr)); } --- Here is what I had written before reading your last comment: I had never heard of it, but strlcat() seems to be a nice/clean option. My code maintains a pointer to the end of the string between iterations in the loop so it couldn't be turned into a strlcat directly, but you can find a strlcat implementation at ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcat.c There may be other places in the code where strlcat and strlcpy could be used to deal more safely with string manipulations. If we go that route we should also add a test to the configure script that would use the system's strlcat/strlcpy if available.
comment:8 by , 20 years ago
Plus I screwed up that code snippet. It should be: repstr[0] = '\0'; for(i=0;i<msObj->NumLayers;i++) { if (i>0) strncat(repstr, " ", sizeof(repstr) - strlen(repstr) - 1); strncat(repstr, msObj->Layers[i], sizeof(repstr) - strlen(repstr) - 1); } It's easy to find strlcat implementations and we could handle just like strcasecmp in configure. However, what are the licensing implications of using it, are you familiar with the BSD license? Strncat is not too bad an option if we're careful with the size computation (always leaving room for the \0), and it's everywhere. If the license issue is no big deal then using strlcat seems like the safest way to go. Steve
comment:9 by , 20 years ago
Ok, the license for the strlcat looks fine. I added the function to mapstring.c and updated configure.in to check for a local copy. The changes have been checked into the development version. I still need to test on a non-BSD'ish system. Will do tomorrow with Linux. Works great on my Mac. So, if others could test that would be great. Once verified I'll apply the changes to the 4.2 branch. Steve
comment:10 by , 20 years ago
Cc: | added |
---|
Things seem to build fine on Linux. Note to Assefa: you'll need to add -DNEED_STRLCAT to the Windows makefiles (unless VC++ provides strlcat() which I doubt)
comment:11 by , 20 years ago
Great, thanks for catching the Windows fix. I'll make the changes to the 4.2 branch tonite.
comment:13 by , 20 years ago
Steve at al: This fix didn't make it into 4.2.1? This would mean that 4.0.2 is the latest version usable as cgi under linux.
comment:14 by , 20 years ago
Guess we'll need a 4.2.2 release soon, perhaps tonite. It may be that not all linuxes are succeptible. Steve
comment:15 by , 20 years ago
Makes sense since the fix was done only in 4.3 (CVS)... that's what I tested when I wrote that things worked on Linux on comment #10. Steve, does this mean that you'll backport this to the 4.2 branch?
comment:17 by , 20 years ago
I copied the changes from the 4.3 development version to the 4.2 branch. Seems to work fine here, but should be testing on Windows. Once tested we can cut a 4.2.2 release (after Sean's tests ;-))... Steve
comment:18 by , 16 years ago
Description: | modified (diff) |
---|---|
Resolution: | → fixed |
Status: | assigned → closed |
Ain't gonna backport anymore... ;-) Closing.
Steve
Note:
See TracTickets
for help on using tickets.