荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: jjksam (UNIX+C+XML+??), 信区: InstallBBS
标  题: .PASSWDS爆掉密技大公开[from nju]
发信站: 荔园晨风BBS站 (Sun Apr 21 21:02:33 2002), 转信

发信人: zhch (zhch), 信区: BBSDev
标  题: Re: [转载] .PASSWDS爆掉密技大公开(转)(转寄)
发信站: 南京大学小百合站 (Fri Dec  8 10:59:13 2000), 站内信件

我那篇文章里面是有点问题,我在想该怎么re比较恰当,呵呵。
似乎主要是赋值时的类型转换的问题。
-------------------------------------------------------------------
【 在 ylsdd (s;dlkf) 的大作中提到: 】
: ft, 那边我等你re呢, 你却跑了 :(
--------------------------------------------------------------------

发信人: zhch (zhch), 信区: BBSDev
标  题: Re: [转载] .PASSWDS爆掉密技大公开(转)(转寄)
发信站: 南京大学小百合站 (Fri Dec  8 10:18:31 2000), 转信

我觉得FB2000遇到的PASSWDS问题不是这个原因,原因有三:

一,文中的问题是可重现, 经常出现的,FB2000的问题是偶然出现,不易重现的。

二,FB3, FB2000中用SEEK_CUR的调用参数都是int, 没有用unsigned的sizeof()
作参数。int在cast到long long时不会有问题的。

三,文中问题只在freebsd等支持大文件的系统下出现,FB2000的问题在linux下也
会出现。
---------------------------------------------------------------------------
发信人: zhch (zhch), 信区: BBSDev
标  题: [转载] .PASSWDS爆掉密技大公开(转)(转寄)
发信站: 南京大学小百合站 (Fri Dec  8 09:53:58 2000), 转信

发信人: Roland (罗兰), 信区: BBSdev
标  题: .PASSWDS爆掉密技大公开(转)
发信站: 快意灌水站 (2000年12月07日21:59:51 星期四), 站内信件


发信人: tmg (海边漂来的..海啸) 看板: InstallBBS
标  题: .PASSWDS 爆掉秘技大公开
发信站: Sat Oct 12 16:07:53 1996
转信站: ACEBBS!
咳.......

.PASSWD 爆掉的问题, 刚刚翻了一下, 发现这个问题有点棘手......


首先, 先说明一下问题的来由吧.......

lseek(fd, offset, method) 中的 offset 参数, 其 type 为 off_t....
在不同的 OS, off_t 这个 type 有些许的不同......


在 LINUX 中, off_t 是 typedef 为 long 的......
(详见 /usr/include/sys/types.h,
/usr/include/asm/posix_types.h)

在 FreeBSD 中, off_t 是 typedef 为 long long 的
(这个 type 是 8-bytes 的整数, 详见 /usr/include/sys/types.h)

这是因为, LINUX 所能支援的档案大小, 最多最多只有 2147483647 bytes
(16进位为 0x7FFFFFFF), 所以用 long 表示 off_t 就够了......
大部分的 UNIX 也都只用到 long 而已)

FreeBSD 比较变态, 它能允许更大的档案存在,
所以, off_t 就非得用 long long 不可了.......

问题来了, 就是 type casting 的问题.......
如果, 我们使用 lseek(fd, 1024, SEEK_SET) 时,
因为 lseek 这个函数已经在 unistd.h 中 prototype 好了,
所以, 即使 1024 的 type 为 int, 但会由 compiler 自动 cast 为 long long....

问题就在这边, eg_lwhaa 兄提到, 他是这样使用 lseek 的:
lseek(fd, (off_t)(-sizeof(userec)), SEEK_CUR);
(那个 (off_t) 有加没加意思完全一样)

这时, compiler 会怎麽解读 (off_t)(-sizeof(userec)) 呢?

首先, sizeof(userec) 值为 256, 但, 其 type 为 unsigned int,
(在大部分的 UNIX 下, unsigned int 和 unsigned long 是一样的东东,
至少, LINUX, FreeBSD, SunOS....... 等均是)
接下来, -sizeof(userec), 在 compiler 的立场而言,
因为其 type 为 unsigned int, 所以, compiler 并不是解释成 -256,
而是 4294967040 (16 进位为 0xFFFFFF00)
这时, 经由 off_t 的 cast 之後, (off_t)(-sizeof(userec)) 就有不同的结果出现:

在 LINUX 底下, 由於 off_t == long,
所以这个 casting 只不过是将无号数变为有号数而已.....

但, 在 FreeBSD 底下, 由於 off_t == long long,
而且, -sizeof(userec) 的 type 为 "unsigned" int,
所以, 这个 casting 会将其扩充成 16 进位的 0x00000000FFFFFF00
(10进位值为 4294967040),
而不是 0xFFFFFFFFFFFFFF00 (10进位值为 -256),
所以, 这时, offset 就增加了 4294967040 bytes, 而不是减少 256 bytes.....

问题的解决方法有两种,
其中一种, 有人提出, 将 -sizeof(userec) cast 成 int 就好了,
因为 (int)(-sizeof(userec)) cast 成 long long 时,
(如前所述, 因 lseek 已经 prototype 过了,
所以 compiler 会自动 cast 成 long long)
会扩充为 0xFFFFFFFFFFFFFF00, 和由 unsigned int cast 时不一样,
所以, 有些网友将 -sizeof(userec) cast 成 int 时会正常 work 就是这个道理.....

第二种, 我比较建议的做法, 就是先将 sizeof(userec)
cast 为 off_t 之後过再做运算, 即写成
lseek(fd, -((off_t) sizeof (userec)), SEEK_CUR);
这样, 无论做什麽运算 (这个例子是在做"负号"这个运算),
用这种方法则保证万无一失........


唉........ 为什麽写程式要注意这些有的没有的问题呢?
--
※ 来源:·快意灌水站 fb2000.dhs.org·[FROM: 202.112.152.17]
--
※ 转寄:·快意灌水站 fb2000.dhs.org·[FROM: 202.119.32.102]
--
※ 转载:.南京大学小百合站 bbs.nju.edu.cn.[FROM: dsl.nju.edu.cn]
--
         ╱▉ ____ ____ ● ●       ╱▉     __▃_
       ╱__▉ ▉__ ▉   ▉ ▉     ╱__▉ ▉╱  ▉
   __╱    ▉ __▉_▉___▉_▉___╱    ▉_▉    ▉_
 ─────────────────────────

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店