Sometimes first character of image CAPTCHA is invisible: weird bug in PHP's bounding box calculation
fundawang - December 19, 2008 - 18:51
| Project: | CAPTCHA |
| Version: | 6.x-2.x-dev |
| Component: | Image Captcha (image_captcha) |
| Category: | support request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs review |
Description
I'm using image captcha with a external ttf font (DejaVu Sans), and set the characters as "0-9" (digits), with 4 digits.
Sometimes it only shows the last three characters. And, with 1.0 rc2, it will show nothing in such cases.

#1
Can give some screenshots of both successes as failures?
And how do you know it's the first character that is chopped off?
#2
I thought about creating a new issue for this, and maybe I should (or it might be a duplicate) but I would love to see a feature of 'redrawing' the image from the user standpoint to resolve issues such as the one posted here.
Is this something that might be feasible?
Update: K, I noticed this has been requested on http://drupal.org/node/180328
I'll leave it at that :)
#3
I'm having trouble with the image captcha as well... about a quarter of the time there is a character missing (should be 5, only displaying 4).
I've tried numerous different TTF files and different font sizes and spacing but have been unable to get around the problem.
Interestingly, it doesn't happen with the built in font. Could it be something to do with UTF-8?
Anybody else having any trouble with this?
Thanks.
#4
does it also happen when distortion is disabled?
and if your site/page is online, can you provide a link to it?
#5
Thanks for the quick response! The problem persists when there is no distortion set.
An example of the problem can be seen at: http://www.network-box.co.uk/feedback/contact-us
#6
I can reproduce on your site, but I can't reproduce on my setup.
can you provide the phpinfo() page of your setup (you can get this from the status report and following the link on the PHP version number, which will lead to something like example.com/?q=admin/reports/status/php)?
#7
Hi,
Sorry for the slow response, Easter holidays here.
I've attached a HTML document with my phpinfo() output in it.
Thanks.
#8
Any ideas??
#9
at #7:
it appears that your setup uses higher versions (PHP, GD) than mine, so that probably isn't the reason.
what happens when you take larger (or smaller) character spacing in the image CAPTCHA settings?
#10
I've tried numerous combinations of ttf fonts, character spacing and font sizes, all with the same result (intermittently there is a character missing). Thanks.
#11
Let's try something else:
in the file
image_captcha/image_captcha.user.inc, you'll find the following lines somewhere near the bottom:<?php// for debugging purposes: draw character bounding box
// imagerectangle($image, $pos_x + $bbox[0], $pos_y + $bbox[1], $pos_x + $bbox[2], $pos_y + $bbox[7], $color);
?>
Uncomment the second line to show the bounding box of each character and report your findings.
#12
Hi,
Interesting results - when working the borders look fine, but when the character is missing there are a couple of lines through the whole image. Attached a couple of screenshots.... thanks for your perseverance with this!
Colin.
#13
Wow, this is really weird.
it looks like the bounding box of the first character is much wider than the canvas, while the height is ok.
Can you leave the bounding box drawing on for some days on you site, so I can try it myself?
#14
Hi,
I've turned the borders back on for now at http://www.network-box.co.uk/feedback/contact-us
Thanks,
Colin.
#15
Could you replace the
imagerectangle()call from #11 with the following:<?phpif (strstr(referer_uri(), 'imagecaptchadebug')) {
imagerectangle($image, $pos_x + $bbox[0], $pos_y + $bbox[1], $pos_x + $bbox[2], $pos_y + $bbox[7], $color);
if ($c == 0) {
$color = imagecolorallocate($image, 0, 0, 0);
imagestring($image, 1, 0, 0, implode(',', $bbox), $color);
}
}
?>
if I add something like "?mode=imagecaptchadebug" to the url of your site, I'll see the bounding box values of the first character, but normal users will see the normal image.
#16
Hi,
I've added the code to show debug information when visiting http://www.network-box.co.uk/feedback/contact-us/?mode=imagecaptchadebug
Hope this helps, thanks.
#17
Apparently, the imagettfbbox returns an invalid value for the x-value of the lower right corner and upper right corner of the character bounding box.
This value is -2147483648 in all cases I've seen, which is -2^31 or 0x80000000 in hexadecimal two's complement notation.
I have absolutely no idea what is going on here. I guess it's a bug in your version of PHP/TTF library, but it's very weird that it only happens sometimes and only for the first character (as far as we observed). I don't have the impression that it depends on the value of the first character itself.
I don't think this is a bug in the image_captcha module itself (that's why I changed the category of this issue to support request).
I googled a bit, but didn't found any pointers to what could be the problem.
I don't know if you have control over your hosting setup, but if you do, I would try to use a different version of PHP or something.
#18
I do have complete control over my hosting set up (I'm more a Linux sysadmin than a PHP developer) and am going to try experimenting with different versions of GD in particular. A quick question though... as a quick and dirty fix... would it be possible to detect if the bug has occurred while the CAPTCHA image is being generated and if so force the script to try again (and loop through this condition until the image is NOT broken?)
Thanks!
#19
Wow soxo you were right.. i tested this through thoroughly and it happens only every few thousand times.. here's a patch with a workaround to catch that single case, and some other fixes (hail E_ALL!)
#20
a bit more tests down the road, this indeed happens more often with non-latin2 characters (using ttf font) but else is quite unpredictable so imho this warrants adding a workaround for buggy GD libs.. it only checks a single integer against being not negative so the overhead is really really negligible. Tests show that usually one regeneration of the bounding box is enough, only very seldomly two. Did not experience higher numbers...
#21
I think I have the same problem after I updated my CAPTCHA module from version 6.x-1.0-rc2 to 6.x-2.0-rc3, which I just reported on http://drupal.org/node/558904.
#22
I was tired seeing only 4 characters on my CAPTCHA image more often recently, so I tried the patch provided by eMPee584 (post #19). The patch seems to work as I always see 5 characters.
However, I just patched captcha.module and image_captcha/image_captcha.user.inc files. I don't see it necessary to add the following lines on the captcha.inc file:
+ if (!isset($_SESSION['captcha_success_form_ids'])) {+ $_SESSION['captcha_success_form_ids'] = array();
+ }
Because the next line is already as below:
$captcha_success_form_ids = isset($_SESSION['captcha_success_form_ids']) ? (array)($_SESSION['captcha_success_form_ids']) : array();Perhaps the #19 patch was done based on 6.x-1.0-rc2 version, and I am using 6.x-2.0-rc3.
#23
(sorry for the delay)
The patch of #19 indeed changes more than just implementing the workaround for this issue (the other changes should be handled separately, e.g.: #545526: undefined indices..).
I worked a bit on the workaround (see attched patch).
For those who are affected by the GD-bug (I'm not, so I cant really check this), please try it out and check if it fixes (workarounds actually) the problem.
#24
@soxofaan
I just would like to understand the patch.
If we knew that it is very likely that the first call result of imagegettfbox is corrupt, why do we need to wait until 5 loops (or 10 loops on #19 patch)?
I tried to limit the loop to only 1 loop as below, and it seems to work fine.
for ($count=0; $bbox[2] < 0 && $count < 1; $count++) {$bbox = imagettfbbox($font_size, 0, realpath($font), $character);
}
Edit:
Actually, it does not make sense at all to use "for" loop command only for 1 loop (duh!) :)
So I changed the command into the following and it seems to work as well.
if ($bbox[2] < 0) {$bbox = imagettfbbox($font_size, 0, realpath($font), $character);
}
#25
@aryanto:
The problem is that I don't have access to a setup with the problem, so I can't really try things out.
The patch in #23 indeed uses a for loop because #20 reports that two retries could be required.
If you can guarantee that only one retry is actually required, I would be more than happy to rip out that for loop and just do an if construct, like you suggest in #24.
#26
@soxofaan
Just from what I experienced, the first character is usually missing after I clear up my browser's cache or after about 50-60 times refresh of the page containing CAPTCHA image. I did that again after I did #24 (without loop) and I have not experienced the issue.
But I am sorry that I can not guarantee whether only one retry would be enough or not. I will leave the setting with "if" construct as #24 for the moment. Lets see if I still experience the issue or I got complain about the missing character :)
Or maybe to be on the safe side a few loops is good to have, as it does not consume significant server's resources anyway.
#27
Got this issue as well, but it seems this is happening on my local linux, haven't seen this happening in the real server (happy about that), but interested in helping in getting this fixed. Workaround might be good, and IMHO, it seems that it would be good to have a loop to make sure a captcha is properly generated, but I'll try to investigate more about this.
#28
I'm seeing this as well.. disabled all noise, color changes etc.. First character seems to be missing most of the time?
bump..
#29
(please leave at 6.x-2.x-dev, which is "higher" than 6.x-2.0)
More importantly however, if you are affected by this bug:
please describe your webserver setup: operating system, apache version, PHP version, GD version, Freetype version, etc
You can find this info on example.com/?q=admin/reports/status/php (Administer > Reports > Status report > click on the PHP version string in the table)