【问题标题】:Compile error :lvalue required as left operand of assignment编译错误:需要左值作为赋值的左操作数
【发布时间】:2016-02-28 14:39:17
【问题描述】:

我是 Linux 和 C 的初学者。 我需要运行我下载的程序,在自述文件中写入运行“make”来构建它的运行包。但是当我运行它时,我得到了这些错误:

~/injectso-0.2$ make
gcc -I./  -c -g -O2 -Wall  procdbg.c
procdbg.c: In function ‘push_stack_proc’:
procdbg.c:149:26: error: lvalue required as left operand of assignment
    (unsigned long) pvEsp -= iSize;
                          ^

procdbg.c: In function ‘restore_syscall’:
procdbg.c:244:49: error: lvalue required as left operand of assignment
          (unsigned long) ptProcStatus->regs.eip = (unsigned long) ptProcStatus->regs.eip - 2; 
                                                 ^
make: *** [procdbg.o] Error 1

似乎转换是错误的,并且将左手赋值给除地址之外的值。这是第一个错误的实际代码:

   void *pvEsp;
   SProcStatus tProcStatus;

   /* If there is no data to be pushed, exit                               */
   if (!iSize)
      return(0);

   /* Get the current ESP                                                  */
   read_status(&(tProcStatus));
   pvEsp = (void *) SP(tProcStatus);

   show_debug(3, "Current ESP is %p\n", pvEsp);

   /* Now subtract the amount of space we need for the                     */
   /* data to be pushed                                                    */
   (unsigned long) pvEsp -= iSize;

我把有问题的线改到最下面了,但还是出现错误:

       (unsigned long *) pvEsp -= iSize;

你有什么建议吗? 我在 VMware 上有 ubuntu 14.04 i686。

编辑:

问题已通过 Slugonamission 答案链接中的补丁解决:

-   (unsigned long) pvEsp -= iSize;
+   pvEsp -= (unsigned long) iSize;

- (unsigned long) ptProcStatus->regs.eip = (unsigned long) ptProcStatus->regs.eip - 2; 
+  ptProcStatus->regs.eip = (unsigned long) ptProcStatus->regs.eip - 2; 

但是对于想了解更多问题信息的人,我个人不太了解,但向您展示了完整的功能代码:

 /* Write a saved eip into the remote process, this                      */
   /* address must NOT be a valid page (i.e it MUST cause                  */
   /* a segfault). For fun we use 0x41414140 (not 41414141                 */
   /* since its nice to have an aligned address)                           */
   pvEip = (void *) 0x41414140;
#if OS_LINUX && CPU_IA32
   push_stack_proc(&pvEip, sizeof(pvEip));
.....



/* push_stack_proc - Push specified data onto the remote                   */
/* stack                                                                   */
void *push_stack_proc(void *pvAddr, int iSize) {
   void *pvEsp;
   SProcStatus tProcStatus;

   /* If there is no data to be pushed, exit                               */
   if (!iSize)
      return(0);

   /* Get the current ESP                                                  */
   read_status(&(tProcStatus));
   pvEsp = (void *) SP(tProcStatus);

   show_debug(3, "Current ESP is %p\n", pvEsp);

   /* Now subtract the amount of space we need for the                     */
   /* data to be pushed                                                    */
    pvEsp -= (unsigned long) iSize;                   //correct line
  //((unsigned long ) pvEsp) -= iSize;                //faulty line

   /* Round it to a multiple of 8 (if it isn't already)                    */
   /* (We use 8 since Sparc requires double word alignment)                */
   pvEsp = (void *) round_down((unsigned long) pvEsp, STACK_ALIGN);

   /* Write the ESP to the process                                         */
   SP(tProcStatus) = (unsigned long) pvEsp;
   if (!write_regs(&(tProcStatus)))
      show_abort("Could not modify stack pointer in target process\n");
   read_status(&(tProcStatus));
   show_debug(3, "New SP is 0x%08x\n", SP(tProcStatus));

   /* Now write the data itself to the remote process                      */
   if (iSize > (write_proc(pvEsp, pvAddr, iSize)))
      show_abort("Could not write to remote process\n");

   return(pvEsp);
}

【问题讨论】:

  • 这看起来好像缺少*。已发布的代码具有如此简单的错误,我对此感到怀疑。我会重新考虑在没有适当知识和审查的情况下使用它。
  • 古代 GCC 2.9 允许非标准的 (type) var = value; 构造。看到这个:stackoverflow.com/questions/20675646/…。现在它不允许这种事情发生。也许这个源代码必须用非常旧的 GCC 编译?
  • 也许pvEsp = (char *)pvEsp - iSize; 是您想要的,对于第一个。如果您可以解释您希望代码具有什么效果,那将有所帮助。对于第二个,这取决于ptProcStatus->regs.eip 的类型。
  • @Olaf 好主意!除此之外,当我想从 packetstorm 下载它时,我的浏览器会提醒它,但我认为是因为它的功能。并从另一个站点下载它,没有任何警报显示给我

标签: c


【解决方案1】:

不,您的解决方案会改变程序的语义(尽管在不知道 isize 是什么或指的是什么的情况下很难说哪个是正确的),例如

int foo = 32;
foo = (unsigned long)foo - 5; // 27
foo = (unsigned long*)foo - 2; // will subtract 2*(sizeof(unsigned long*))

强制转换的结果不是左值,不能赋值,应该重写,而不是强制转换回原始值,例如

pvEsp = (void*)((unsigned long)pvPsp - iSize);

在 C 中,可以省略转换回 void* 并且是隐式的,没有警告。

此外,Gentoo 开发人员似乎有一个补丁可以解决这个问题,可以在这里找到:https://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/dev-util/injectso/files/injectso-0.2-gcc4.patch

【讨论】:

  • 感谢补丁链接,已更正。但我不明白你的例子中发生了什么!(减去2 *(大小...))你能提供一个参考吗?
  • @qwrt747 - 我真的没有一般的参考,但你需要查看指针算法的工作原理;将1 添加到指针将增加指针以指向“下一个”数据值,因此逻辑上将添加指向的数据的大小而不是下一个字节。
【解决方案2】:

从您的代码 sn-p 和错误看来,iSize 是一个值而不是地址,pvEsp 是一个地址。如下更改故障行,应该可以解决编译错误-

*(unsigned long *) pvEsp -= iSize;

【讨论】:

  • 您的解决方案似乎也解决了,(至少在编译时)。我不知道它在逻辑上是否有效。谢谢
猜你喜欢
  • 1970-01-01
  • 2012-04-09
  • 2011-12-20
  • 2011-03-04
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多