From patchwork Fri Dec 24 01:26:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 76564 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 56475B70D5 for ; Fri, 24 Dec 2010 12:26:30 +1100 (EST) Received: (qmail 5725 invoked by alias); 24 Dec 2010 01:26:29 -0000 Received: (qmail 5717 invoked by uid 22791); 24 Dec 2010 01:26:28 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 24 Dec 2010 01:26:23 +0000 Received: from wpaz29.hot.corp.google.com (wpaz29.hot.corp.google.com [172.24.198.93]) by smtp-out.google.com with ESMTP id oBO1QLQ7015528 for ; Thu, 23 Dec 2010 17:26:21 -0800 Received: from iwn2 (iwn2.prod.google.com [10.241.68.66]) by wpaz29.hot.corp.google.com with ESMTP id oBO1QAMa019894 (version=TLSv1/SSLv3 cipher=RC4-MD5 bits=128 verify=NOT) for ; Thu, 23 Dec 2010 17:26:20 -0800 Received: by iwn2 with SMTP id 2so7119960iwn.21 for ; Thu, 23 Dec 2010 17:26:20 -0800 (PST) Received: by 10.42.239.74 with SMTP id kv10mr9012773icb.506.1293153980161; Thu, 23 Dec 2010 17:26:20 -0800 (PST) Received: from coign.google.com ([216.239.45.130]) by mx.google.com with ESMTPS id u5sm7196935ics.6.2010.12.23.17.26.18 (version=TLSv1/SSLv3 cipher=RC4-MD5); Thu, 23 Dec 2010 17:26:19 -0800 (PST) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Avoid endless loop on array with recursive length Date: Thu, 23 Dec 2010 17:26:16 -0800 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Invalid Go code like var V [len(V) - 1]byte would send the Go frontend into an endless loop trying to check and compute the length of the array. This patch avoids the endless loop and gives an appropriate error. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian diff -r 5fe1c95babee go/expressions.cc --- a/go/expressions.cc Thu Dec 23 16:48:52 2010 -0800 +++ b/go/expressions.cc Thu Dec 23 17:22:54 2010 -0800 @@ -6463,6 +6463,9 @@ Gogo* gogo_; // The builtin function being called. Builtin_function_code code_; + // Used to stop endless loops when the length of an array uses len + // or cap of the array itself. + mutable bool seen_; }; Builtin_call_expression::Builtin_call_expression(Gogo* gogo, @@ -6471,7 +6474,7 @@ bool is_varargs, source_location location) : Call_expression(fn, args, is_varargs, location), - gogo_(gogo), code_(BUILTIN_INVALID) + gogo_(gogo), code_(BUILTIN_INVALID), seen_(false) { Func_expression* fnexp = this->fn()->func_expression(); gcc_assert(fnexp != NULL); @@ -6781,6 +6784,9 @@ case BUILTIN_LEN: case BUILTIN_CAP: { + if (this->seen_) + return false; + Expression* arg = this->one_arg(); if (arg == NULL) return false; @@ -6793,10 +6799,15 @@ if (arg_type->array_type() != NULL && arg_type->array_type()->length() != NULL) - return arg_type->array_type()->length()->is_constant(); + return true; if (this->code_ == BUILTIN_LEN && arg_type->is_string_type()) - return arg->is_constant(); + { + this->seen_ = true; + bool ret = arg->is_constant(); + this->seen_ = false; + return ret; + } } break; @@ -6868,8 +6879,13 @@ if (arg_type->array_type() != NULL && arg_type->array_type()->length() != NULL) { + if (this->seen_) + return false; Expression* e = arg_type->array_type()->length(); - if (e->integer_constant_value(iota_is_constant, val, ptype)) + this->seen_ = true; + bool r = e->integer_constant_value(iota_is_constant, val, ptype); + this->seen_ = false; + if (r) { *ptype = Type::lookup_integer_type("int"); return true; @@ -7484,7 +7500,18 @@ gcc_assert(args != NULL && args->size() == 1); Expression* arg = *args->begin(); Type* arg_type = arg->type(); + + if (this->seen_) + { + gcc_assert(saw_errors()); + return error_mark_node; + } + this->seen_ = true; + tree arg_tree = arg->get_tree(context); + + this->seen_ = false; + if (arg_tree == error_mark_node) return error_mark_node; @@ -7503,7 +7530,16 @@ if (arg_type->is_string_type()) val_tree = String_type::length_tree(gogo, arg_tree); else if (arg_type->array_type() != NULL) - val_tree = arg_type->array_type()->length_tree(gogo, arg_tree); + { + if (this->seen_) + { + gcc_assert(saw_errors()); + return error_mark_node; + } + this->seen_ = true; + val_tree = arg_type->array_type()->length_tree(gogo, arg_tree); + this->seen_ = false; + } else if (arg_type->map_type() != NULL) { static tree map_len_fndecl; @@ -7532,7 +7568,17 @@ else { if (arg_type->array_type() != NULL) - val_tree = arg_type->array_type()->capacity_tree(gogo, arg_tree); + { + if (this->seen_) + { + gcc_assert(saw_errors()); + return error_mark_node; + } + this->seen_ = true; + val_tree = arg_type->array_type()->capacity_tree(gogo, + arg_tree); + this->seen_ = false; + } else if (arg_type->channel_type() != NULL) { static tree chan_cap_fndecl;