通过消息队列接收单个消息时堆栈粉碎
stack smashing when receiving a single message through message queues
我有以下发件人:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>
typedef struct message {
long int mtype;
int mtext[200];
} message;
int main(int argc, char *argv[]) {
// msg queue
int msgid;
message msg;
key_t key;
// create msg queue key
if ((key = ftok("master.c", 'b')) == -1) {
perror("ftok");
}
// create msg queue
if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
perror("msgget");
}
msg.mtype=10;
msg.mtext[0] = 1;
if ((msgsnd(msgid, &msg, sizeof(message), 0)) == -1) {
perror("msgsnd");
}
sleep(5);
// TODO: uncomment section
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl");
}
return 0;
}
接收者:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>
typedef struct message {
long int mtype;
int mtext[200];
} message;
int main(int argc, char *argv[]) {
// msg queue
message msg;
int msgid;
key_t key;
// create msg queue key
if ((key = ftok("master.c", 'b')) == -1) {
perror("ftok");
}
// create msg queue
if ((msgid = msgget(key, 0666)) == -1) {
perror("msgget");
}
if ((msgrcv(msgid, &msg, sizeof(message), 10, 0)) == -1) {
perror("msgrcv");
}
printf("%d\n", msg.mtext[0]);
return 0;
}
问题是当我 运行 他们两个时,我得到
*** stack smashing detected ***: terminated
Aborted (core dumped)
上面的短语是在整个代码按预期执行后显示的,但仍然意味着有些地方不对。但是,如果我将 msgrcv
置于无限循环中,则所有 运行 都按预期 和 不会发出警告。由于我正在写入和读取相同大小的数据,错误可能来自哪里?
根据 the documentation,msgrcv
的 msgsz 参数应指示 [=11] 的大小(以字节为单位) =] 消息结构的成员,而不是整个 结构的大小。
该结构通常比可用缓冲区大 4 或 8 个字节(取决于 long int
的定义方式),因此您可能写入超出 available/assigned 内存 - 导致未定义的行为。
该 UB 的一个可能影响是损坏分配给 main
函数的堆栈;如果该函数永远不会 returns(就像添加无限循环时一样),则堆栈损坏 可能 不会自行显现。
我有以下发件人:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>
typedef struct message {
long int mtype;
int mtext[200];
} message;
int main(int argc, char *argv[]) {
// msg queue
int msgid;
message msg;
key_t key;
// create msg queue key
if ((key = ftok("master.c", 'b')) == -1) {
perror("ftok");
}
// create msg queue
if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
perror("msgget");
}
msg.mtype=10;
msg.mtext[0] = 1;
if ((msgsnd(msgid, &msg, sizeof(message), 0)) == -1) {
perror("msgsnd");
}
sleep(5);
// TODO: uncomment section
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl");
}
return 0;
}
接收者:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>
typedef struct message {
long int mtype;
int mtext[200];
} message;
int main(int argc, char *argv[]) {
// msg queue
message msg;
int msgid;
key_t key;
// create msg queue key
if ((key = ftok("master.c", 'b')) == -1) {
perror("ftok");
}
// create msg queue
if ((msgid = msgget(key, 0666)) == -1) {
perror("msgget");
}
if ((msgrcv(msgid, &msg, sizeof(message), 10, 0)) == -1) {
perror("msgrcv");
}
printf("%d\n", msg.mtext[0]);
return 0;
}
问题是当我 运行 他们两个时,我得到
*** stack smashing detected ***: terminated
Aborted (core dumped)
上面的短语是在整个代码按预期执行后显示的,但仍然意味着有些地方不对。但是,如果我将 msgrcv
置于无限循环中,则所有 运行 都按预期 和 不会发出警告。由于我正在写入和读取相同大小的数据,错误可能来自哪里?
根据 the documentation,msgrcv
的 msgsz 参数应指示 [=11] 的大小(以字节为单位) =] 消息结构的成员,而不是整个 结构的大小。
该结构通常比可用缓冲区大 4 或 8 个字节(取决于 long int
的定义方式),因此您可能写入超出 available/assigned 内存 - 导致未定义的行为。
该 UB 的一个可能影响是损坏分配给 main
函数的堆栈;如果该函数永远不会 returns(就像添加无限循环时一样),则堆栈损坏 可能 不会自行显现。