db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: Prevent a division by 0

PiperOrigin-RevId: 371007407
Change-Id: Iecf2718de48d6bf5a69b02a9df9deda8ec1b19d3
CVE: CVE-2021-29604
CWE: CWE-703
Vulnerability description: TensorFlow is an end-to-end open source platform for machine learning. The TFLite implementation of hashtable lookup is vulnerable to a division by zero error(https://github.com/tensorflow/tensorflow/blob/1a8e885b864c818198a5b2c0cbbeca5a1e833bc8/tensorflow/lite/kernels/hashtable_lookup.cc#L114-L115) An attacker can craft a model such that `values`'s first dimension would be 0. The fix will be included in TensorFlow 2.5.0. We will also cherrypick this commit on TensorFlow 2.4.2, TensorFlow 2.3.3, TensorFlow 2.2.3 and TensorFlow 2.1.4, as these are also affected and still in supported range.

Project: tensorflow
File: hashtable_lookup.cc

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  TfLiteTensor* output;
  TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, 0, &output));
  TfLiteTensor* hits;
  TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, 1, &hits));
  const TfLiteTensor* lookup;
  TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, 0, &lookup));
  const TfLiteTensor* key;
  TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, 1, &key));
  const TfLiteTensor* value;
  TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, 2, &value));

  const int num_rows = SizeOfDimension(value, 0);
  const int row_bytes = value->bytes / num_rows;
  void* pointer = nullptr;
  DynamicBuffer buf;

  for (int i = 0; i < SizeOfDimension(lookup, 0); i++) {
    int idx = -1;
    pointer = bsearch(&(lookup->data.i32[i]), key->data.i32, num_rows,
                      sizeof(int32_t), greater);
    if (pointer != nullptr) {
      idx = (reinterpret_cast<char*>(pointer) - (key->data.raw)) /
            sizeof(int32_t);
    }

    if (idx >= num_rows || idx < 0) {
      if (output->type == kTfLiteString) {
        buf.AddString(nullptr, 0);
      } else {
        memset(output->data.raw + i * row_bytes, 0, row_bytes);
      }
      hits->data.uint8[i] = 0;
    } else {
      if (output->type == kTfLiteString) {
        buf.AddString(GetString(value, idx));
      } else {
        memcpy(output->data.raw + i * row_bytes,
               value->data.raw + idx * row_bytes, row_bytes);
      }
      hits->data.uint8[i] = 1;
    }
  }
  if (output->type == kTfLiteString) {
    buf.WriteToTensorAsVector(output);
  }

  return kTfLiteOk;
}
Commit message: Fix vulnerability in enc_untrusted_recvfrom

Change recvfrom memcpy to check for received_buffer size to avoid
copying extra buffer.

This issue was reported by Qinkun Bao, Zhaofeng Chen, Mingshen Sun, and
Kang Li from Baidu Security.

PiperOrigin-RevId: 322476299
Change-Id: I3606ff9ec51ec7cc4312c7555c645a2fc6e09b21
CVE: CVE-2020-8905
CWE: CWE-787
Vulnerability description: A buffer length validation vulnerability in Asylo versions prior to 0.6.0 allows an attacker to read data they should not have access to. The 'enc_untrusted_recvfrom' function generates a return value which is deserialized by 'MessageReader', and copied into three different 'extents'. The length of the third 'extents' is controlled by the outside world, and not verified on copy, allowing the attacker to force Asylo to copy trusted memory data into an untrusted buffer of significantly small length.. We recommend updating Asylo to version 0.6.0 or later.

Project: asylo
File: host_calls.cc

ssize_t enc_untrusted_recvfrom(int sockfd, void *buf, size_t len, int flags,
                               struct sockaddr *src_addr, socklen_t *addrlen) {
  int klinux_flags = TokLinuxRecvSendFlag(flags);
  if (klinux_flags == 0 && flags != 0) {
    errno = EINVAL;
    return -1;
  }

  MessageWriter input;
  input.Push<int>(sockfd);
  input.Push<uint64_t>(len);
  input.Push<int>(klinux_flags);
  MessageReader output;
  const auto status = NonSystemCallDispatcher(
      ::asylo::host_call::kRecvFromHandler, &input, &output);
  CheckStatusAndParamCount(status, output, "enc_untrusted_recvfrom", 4);

  int result = output.next<int>();
  int klinux_errno = output.next<int>();
  // recvfrom() returns -1 on failure, with errno set to indicate the cause
  // of the error.
  if (result == -1) {
    errno = FromkLinuxErrorNumber(klinux_errno);
    return result;
  }

  auto buffer_received = output.next();
  memcpy(buf, buffer_received.data(), len);

  // If |src_addr| is not NULL, and the underlying protocol provides the source
  // address, this source address is filled in. When |src_addr| is NULL, nothing
  // is filled in; in this case, |addrlen| is not used, and should also be NULL.
  if (src_addr != nullptr && addrlen != nullptr) {
    auto klinux_sockaddr_buf = output.next();
    const struct klinux_sockaddr *klinux_addr =
        klinux_sockaddr_buf.As<struct klinux_sockaddr>();
    FromkLinuxSockAddr(klinux_addr, klinux_sockaddr_buf.size(), src_addr,
                       addrlen, TrustedPrimitives::BestEffortAbort);
  }

  return result;
}
Commit message: Prevent division by 0

PiperOrigin-RevId: 370998952
Change-Id: I6b1d49079624ee1447d2d9b53a8976fb356cc8f5
CVE: CVE-2021-29599
CWE: CWE-369
Vulnerability description: TensorFlow is an end-to-end open source platform for machine learning. The implementation of the `Split` TFLite operator is vulnerable to a division by zero error(https://github.com/tensorflow/tensorflow/blob/e2752089ef7ce9bcf3db0ec618ebd23ea119d0c7/tensorflow/lite/kernels/split.cc#L63-L65). An attacker can craft a model such that `num_splits` would be 0. The fix will be included in TensorFlow 2.5.0. We will also cherrypick this commit on TensorFlow 2.4.2, TensorFlow 2.3.3, TensorFlow 2.2.3 and TensorFlow 2.1.4, as these are also affected and still in supported range.

Project: tensorflow
File: split.cc

TfLiteStatus ResizeOutputTensors(TfLiteContext* context, TfLiteNode* node,
                                 const TfLiteTensor* axis,
                                 const TfLiteTensor* input, int num_splits) {
  int axis_value = GetTensorData<int>(axis)[0];
  if (axis_value < 0) {
    axis_value += NumDimensions(input);
  }

  TF_LITE_ENSURE(context, axis_value >= 0);
  TF_LITE_ENSURE(context, axis_value < NumDimensions(input));

  const int input_size = SizeOfDimension(input, axis_value);
  TF_LITE_ENSURE_MSG(context, input_size % num_splits == 0,
                     "Not an even split");
  const int slice_size = input_size / num_splits;

  for (int i = 0; i < NumOutputs(node); ++i) {
    TfLiteIntArray* output_dims = TfLiteIntArrayCopy(input->dims);
    output_dims->data[axis_value] = slice_size;
    TfLiteTensor* output;
    TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, i, &output));
    TF_LITE_ENSURE_STATUS(context->ResizeTensor(context, output, output_dims));
  }

  return kTfLiteOk;
}
Commit message: pict: Fixed a bug with ICC profile extraction

Could cause a NULL pointer dereference.

Found by F. Çelik.
CVE: CVE-2021-28855
CWE: CWE-476
Vulnerability description: In Deark before 1.5.8, a specially crafted input file can cause a NULL pointer dereference in the dbuf_write function (src/deark-dbuf.c).

Project: deark
File: pict.c

static void do_iccprofile_item(deark *c, lctx *d, i64 pos, i64 len)
{
	i64 selector;
	i64 data_len;

	if(len<4) return;
	selector = de_getu32be(pos);
	data_len = len-4;
	de_dbg(c, "ICC profile segment, selector=%d, data len=%d", (int)selector,
		(int)data_len);

	if(selector!=1) {
		// If this is not a Continuation segment, close any current file.
		dbuf_close(d->iccprofile_file);
		d->iccprofile_file = NULL;
	}

	if(selector==0) { // Beginning segment
		d->iccprofile_file = dbuf_create_output_file(c, "icc", NULL, DE_CREATEFLAG_IS_AUX);
	}

	if(selector==0 || selector==1) {
		// Beginning and Continuation segments normally have profile data.
		// End segments (selector==2) are not allowed to include data.
		dbuf_copy(c->infile, pos+4, data_len, d->iccprofile_file);
	}
}
Commit message: Fix tf.raw_ops.TensorSummaryV2 vulnerability with invalid serialized_summary_metadata.

Check that input is actually a scalar before treating it as such.

PiperOrigin-RevId: 445197183
CVE: CVE-2022-29193
CWE: CWE-703
Vulnerability description: TensorFlow is an open source platform for machine learning. Prior to versions 2.9.0, 2.8.1, 2.7.2, and 2.6.4, the implementation of `tf.raw_ops.TensorSummaryV2` does not fully validate the input arguments. This results in a `CHECK`-failure which can be used to trigger a denial of service attack. Versions 2.9.0, 2.8.1, 2.7.2, and 2.6.4 contain a patch for this issue.

Project: tensorflow
File: summary_tensor_op.cc

  void Compute(OpKernelContext* c) override {
    const Tensor& tag = c->input(0);
    OP_REQUIRES(c, TensorShapeUtils::IsScalar(tag.shape()),
                errors::InvalidArgument("tag must be scalar"));
    const Tensor& tensor = c->input(1);
    const Tensor& serialized_summary_metadata_tensor = c->input(2);

    Summary s;
    Summary::Value* v = s.add_value();
    v->set_tag(string(tag.scalar<tstring>()()));  // NOLINT

    if (tensor.dtype() == DT_STRING) {
      // tensor_util.makeNdarray doesn't work for strings in tensor_content
      tensor.AsProtoField(v->mutable_tensor());
    } else {
      tensor.AsProtoTensorContent(v->mutable_tensor());
    }

    ParseFromTString(serialized_summary_metadata_tensor.scalar<tstring>()(),
                     v->mutable_metadata());

    Tensor* summary_tensor = nullptr;
    OP_REQUIRES_OK(c, c->allocate_output(0, TensorShape({}), &summary_tensor));
    CHECK(SerializeToTString(s, &summary_tensor->scalar<tstring>()()));
  }
Commit message: SECUNIA advisory 76000 #1 (wrong fuji width set via tiff tag
CVE: CVE-2017-16909
CWE: CWE-125
Vulnerability description: An error related to the "LibRaw::panasonic_load_raw()" function (dcraw_common.cpp) in LibRaw versions prior to 0.18.6 can be exploited to cause a heap-based buffer overflow and subsequently cause a crash via a specially crafted TIFF image.

Project: LibRaw
File: dcraw.c

void CLASS panasonic_load_raw()
{
  int row, col, i, j, sh = 0, pred[2], nonz[2];

  pana_bits(0);
  for (row = 0; row < height; row++)
  {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
    for (col = 0; col < raw_width; col++)
    {
      if ((i = col % 14) == 0)
        pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
      if (i % 3 == 2)
        sh = 4 >> (3 - pana_bits(2));
      if (nonz[i & 1])
      {
        if ((j = pana_bits(8)))
        {
          if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
            pred[i & 1] &= ~((~0u) << sh);
          pred[i & 1] += j << sh;
        }
      }
      else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
        pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
      if ((RAW(row, col) = pred[col & 1]) > 4098 && col < width)
        derror();
    }
  }
}
Commit message: minor: Fix overflow in Clipsal-CMR113 and Somfy-IOHC reported by aug5t7
CVE: CVE-2022-25051
CWE: CWE-703
Vulnerability description: An Off-by-one Error occurs in cmr113_decode of rtl_433 21.12 when decoding a crafted file.

Project: rtl_433
File: somfy_iohc.c

static int somfy_iohc_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    uint8_t const preamble_pattern[] = {0x57, 0xfd, 0x99};

    uint8_t b[19 + 15]; // 19 byte + up 15 byte payload

    if (bitbuffer->num_rows != 1)
        return DECODE_ABORT_EARLY;

    int offset = bitbuffer_search(bitbuffer, 0, 0, preamble_pattern, 24) + 24;
    if (offset >= bitbuffer->bits_per_row[0] - 19 * 10)
        return DECODE_ABORT_EARLY;

    int num_bits = bitbuffer->bits_per_row[0] - offset;

    int len = extract_bytes_uart(bitbuffer->bb[0], offset, num_bits, b);
    if (len < 19)
        return DECODE_ABORT_LENGTH;

    if ((b[0] & 0xf0) != 0xf0)
        return DECODE_ABORT_EARLY;

    int msg_len = b[0] & 0xf; // should be 6 or 8
    if (len < 19 + msg_len)
        return DECODE_ABORT_LENGTH;

    // calculate and verify checksum
    if (crc16lsb(b, len, 0x8408, 0x0000) != 0) // unreflected poly 0x1021
        return DECODE_FAIL_MIC;
    bitrow_printf(b, len * 8, "%s: offset %d, num_bits %d, len %d, msg_len %d\n", __func__, offset, num_bits, len, msg_len);

    int msg_type = (b[0]);
    int dst_id   = ((unsigned)b[4] << 24) | (b[3] << 16) | (b[2] << 8) | (b[1]); // assume Little-Endian
    int src_id   = ((unsigned)b[8] << 24) | (b[7] << 16) | (b[6] << 8) | (b[5]); // assume Little-Endian
    int counter  = (b[len - 10] << 8) | (b[len - 9]);
    char msg_str[15 * 2 + 1];
    bitrow_snprint(&b[9], msg_len * 8, msg_str, 15 * 2 + 1);
    char mac_str[13];
    bitrow_snprint(&b[len - 8], 6 * 8, mac_str, 13);

    /* clang-format off */
    data_t *data = data_make(
            "model",            "",                 DATA_STRING, "Somfy-IOHC",
            "id",               "",                 DATA_FORMAT, "%08x", DATA_INT, src_id,
            "dst_id",           "Dest ID",          DATA_FORMAT, "%08x", DATA_INT, dst_id,
            "msg_type",         "Msg type",         DATA_FORMAT, "%02x", DATA_INT, msg_type,
            "msg",              "Message",          DATA_STRING, msg_str,
            "counter",          "Counter",          DATA_INT,    counter,
            "mac",              "MAC",              DATA_STRING, mac_str,
            "mic",              "Integrity",        DATA_STRING, "CRC",
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);
    return 1;
}
Commit message: fix UAF in audio_sample_entry_Read (#1440)
CVE: CVE-2020-11558
CWE: CWE-416
Vulnerability description: An issue was discovered in libgpac.a in GPAC 0.8.0, as demonstrated by MP4Box. audio_sample_entry_Read in isomedia/box_code_base.c does not properly decide when to make gf_isom_box_del calls. This leads to various use-after-free outcomes involving mdia_Read, gf_isom_delete_movie, and gf_isom_parse_movie_boxes.

Project: gpac
File: box_code_base.c

GF_Err audio_sample_entry_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_MPEGAudioSampleEntryBox *ptr;
	char *data;
	u8 a, b, c, d;
	u32 i, size, v, nb_alnum;
	GF_Err e;
	u64 pos, start;

	ptr = (GF_MPEGAudioSampleEntryBox *)s;

	start = gf_bs_get_position(bs);
	gf_bs_seek(bs, start + 8);
	v = gf_bs_read_u16(bs);
	if (v)
		ptr->is_qtff = 1;

	//try to disambiguate QTFF v1 and MP4 v1 audio sample entries ...
	if (v==1) {
		//go to end of ISOM audio sample entry, skip 4 byte (box size field), read 4 bytes (box type) and check if this looks like a box
		gf_bs_seek(bs, start + 8 + 20  + 4);
		a = gf_bs_read_u8(bs);
		b = gf_bs_read_u8(bs);
		c = gf_bs_read_u8(bs);
		d = gf_bs_read_u8(bs);
		nb_alnum = 0;
		if (isalnum(a)) nb_alnum++;
		if (isalnum(b)) nb_alnum++;
		if (isalnum(c)) nb_alnum++;
		if (isalnum(d)) nb_alnum++;
		if (nb_alnum>2) ptr->is_qtff = 0;
	}

	gf_bs_seek(bs, start);
	e = gf_isom_audio_sample_entry_read((GF_AudioSampleEntryBox*)s, bs);
	if (e) return e;
	pos = gf_bs_get_position(bs);
	size = (u32) s->size;

	//when cookie is set on bs, always convert qtff-style mp4a to isobmff-style
	//since the conversion is done in addBox and we don't have the bitstream there (arg...), flag the box
 	if (gf_bs_get_cookie(bs)) {
 		ptr->is_qtff |= 1<<16;
 	}

	e = gf_isom_box_array_read(s, bs, audio_sample_entry_AddBox);
	if (!e) return GF_OK;
	if (size<8) return GF_ISOM_INVALID_FILE;

	/*hack for some weird files (possibly recorded with live.com tools, needs further investigations)*/
	gf_bs_seek(bs, pos);
	data = (char*)gf_malloc(sizeof(char) * size);
	gf_bs_read_data(bs, data, size);
	for (i=0; i<size-8; i++) {
		if (GF_4CC((u32)data[i+4], (u8)data[i+5], (u8)data[i+6], (u8)data[i+7]) == GF_ISOM_BOX_TYPE_ESDS) {
			GF_BitStream *mybs = gf_bs_new(data + i, size - i, GF_BITSTREAM_READ);
			if (ptr->esd) {
				gf_isom_box_del((GF_Box *)ptr->esd);
				ptr->esd=NULL;
			}

			e = gf_isom_box_parse((GF_Box **)&ptr->esd, mybs);

			if (e==GF_OK) {
				gf_isom_box_add_for_dump_mode((GF_Box*)ptr, (GF_Box*)ptr->esd);
			} else if (ptr->esd) {
				gf_isom_box_del((GF_Box *)ptr->esd);
				ptr->esd=NULL;
			}

			gf_bs_del(mybs);
			break;
		}
	}
	gf_free(data);
	return e;
}
Commit message: Don't inflate more than ~16mb, drop connection on inflate error
CVE: CVE-2016-10544
CWE: CWE-20
Vulnerability description: uws is a WebSocket server library. By sending a 256mb websocket message to a uws server instance with permessage-deflate enabled, there is a possibility used compression will shrink said 256mb down to less than 16mb of websocket payload which passes the length check of 16mb payload. This data will then inflate up to 256mb and crash the node process by exceeding V8's maximum string size. This affects uws >=0.10.0 <=0.10.8.

Project: uWebSockets
File: Hub.cpp

char *Hub::inflate(char *data, size_t &length) {
    dynamicInflationBuffer.clear();

    inflationStream.next_in = (Bytef *) data;
    inflationStream.avail_in = length;

    int err;
    do {
        inflationStream.next_out = (Bytef *) inflationBuffer;
        inflationStream.avail_out = LARGE_BUFFER_SIZE;
        err = ::inflate(&inflationStream, Z_FINISH);
        if (!inflationStream.avail_in) {
            break;
        }
        dynamicInflationBuffer.append(inflationBuffer, LARGE_BUFFER_SIZE - inflationStream.avail_out);
    } while (err == Z_BUF_ERROR);

    inflateReset(&inflationStream);

    if (err != Z_BUF_ERROR && err != Z_OK) {
        length = 0;
        return nullptr;
    }

    if (dynamicInflationBuffer.length()) {
        dynamicInflationBuffer.append(inflationBuffer, LARGE_BUFFER_SIZE - inflationStream.avail_out);

        length = dynamicInflationBuffer.length();
        return (char *) dynamicInflationBuffer.data();
    }

    length = LARGE_BUFFER_SIZE - inflationStream.avail_out;
    return inflationBuffer;
}
Commit message: Fix heap-buffer-overflow issue with `tf.raw_ops.SparseReshape`.

PiperOrigin-RevId: 371218558
Change-Id: I6a6dc5bf15b50a1d05bdd95e9ba347cb39f40f45
CVE: CVE-2021-29611
CWE: CWE-369
Vulnerability description: TensorFlow is an end-to-end open source platform for machine learning. Incomplete validation in `SparseReshape` results in a denial of service based on a `CHECK`-failure. The implementation(https://github.com/tensorflow/tensorflow/blob/e87b51ce05c3eb172065a6ea5f48415854223285/tensorflow/core/kernels/sparse_reshape_op.cc#L40) has no validation that the input arguments specify a valid sparse tensor. The fix will be included in TensorFlow 2.5.0. We will also cherrypick this commit on TensorFlow 2.4.2 and TensorFlow 2.3.3, as these are the only affected versions.

Project: tensorflow
File: sparse_reshape_op.cc

  void Compute(OpKernelContext* context) override {
    ReshapeSparseTensor<Device>(context, context->input(0), context->input(1),
                                context->input(2), 0 /* output indices index */,
                                1 /* output shape index */);
  }
Commit message: Work around shell code in podcast names (#598)
CVE: CVE-2017-14500
CWE: CWE-78
Vulnerability description: Improper Neutralization of Special Elements used in an OS Command in the podcast playback function of Podbeuter in Newsbeuter 0.3 through 2.9 allows remote attackers to perform user-assisted code execution by crafting an RSS item with a media enclosure (i.e., a podcast file) that includes shell metacharacters in its filename, related to pb_controller.cpp and queueloader.cpp, a different vulnerability than CVE-2017-12904.

Project: newsbeuter
File: queueloader.cpp

std::string queueloader::get_filename(const std::string& str) {
	std::string fn = ctrl->get_dlpath();

	if (fn[fn.length()-1] != NEWSBEUTER_PATH_SEP[0])
		fn.append(NEWSBEUTER_PATH_SEP);
	char buf[1024];
	snprintf(buf, sizeof(buf), "%s", str.c_str());
	char * base = basename(buf);
	if (!base || strlen(base) == 0) {
		char lbuf[128];
		time_t t = time(nullptr);
		strftime(lbuf, sizeof(lbuf), "%Y-%b-%d-%H%M%S.unknown", localtime(&t));
		fn.append(lbuf);
	} else {
		fn.append(base);
	}
	return fn;
}

Project: newsbeuter
File: pb_controller.cpp

void pb_controller::play_file(const std::string& file) {
	std::string cmdline;
	std::string player = cfg->get_configvalue("player");
	if (player == "")
		return;
	cmdline.append(player);
	cmdline.append(" \"");
	cmdline.append(utils::replace_all(file,"\"", "\\\""));
	cmdline.append("\"");
	stfl::reset();
	utils::run_interactively(cmdline, "pb_controller::play_file");
}
Commit message: snapshot of project "xterm", label xterm-365d
CVE: CVE-2021-27135
CWE: CWE-399
Vulnerability description: xterm before Patch #366 allows remote attackers to execute arbitrary code or cause a denial of service (segmentation fault) via a crafted UTF-8 combining character sequence.

Project: xterm-snapshots

SaltTextAway(XtermWidget xw,
	     int which,
	     CELL *cellc,
	     CELL *cell)
{
    TScreen *screen = TScreenOf(xw);
    SelectedCells *scp;
    int i;
    int eol;
    int need = 0;
    Char *line;
    Char *lp;
    CELL first = *cellc;
    CELL last = *cell;

    if (which < 0 || which >= MAX_SELECTIONS) {
	TRACE(("SaltTextAway - which selection?\n"));
	return;
    }
    scp = &(screen->selected_cells[which]);

    TRACE(("SaltTextAway which=%d, first=%d,%d, last=%d,%d\n",
	   which, first.row, first.col, last.row, last.col));

    if (isSameRow(&first, &last) && first.col > last.col) {
	int tmp;
	EXCHANGE(first.col, last.col, tmp);
    }

    --last.col;
    /* first we need to know how long the string is before we can save it */

    if (isSameRow(&last, &first)) {
	need = Length(screen, first.row, first.col, last.col);
    } else {			/* two cases, cut is on same line, cut spans multiple lines */
	need += Length(screen, first.row, first.col, screen->max_col) + 1;
	for (i = first.row + 1; i < last.row; i++)
	    need += Length(screen, i, 0, screen->max_col) + 1;
	if (last.col >= 0)
	    need += Length(screen, last.row, 0, last.col);
    }

    /* UTF-8 may require more space */
    if_OPT_WIDE_CHARS(screen, {
	need *= 4;
    });

    /* now get some memory to save it in */
    if (need < 0)
	return;

    if (scp->data_limit <= (unsigned) need) {
	if ((line = (Char *) malloc((size_t) need + 1)) == 0)
	    SysError(ERROR_BMALLOC2);
	free(scp->data_buffer);
	scp->data_buffer = line;
	scp->data_limit = (size_t) (need + 1);
    } else {
	line = scp->data_buffer;
    }

    if (line == 0)
	return;

    line[need] = '\0';		/* make sure it is null terminated */
    lp = line;			/* lp points to where to save the text */
    if (isSameRow(&last, &first)) {
	lp = SaveText(screen, last.row, first.col, last.col, lp, &eol);
    } else {
	lp = SaveText(screen, first.row, first.col, screen->max_col, lp, &eol);
	if (eol)
	    *lp++ = '\n';	/* put in newline at end of line */
	for (i = first.row + 1; i < last.row; i++) {
	    lp = SaveText(screen, i, 0, screen->max_col, lp, &eol);
	    if (eol)
		*lp++ = '\n';
	}
	if (last.col >= 0)
	    lp = SaveText(screen, last.row, 0, last.col, lp, &eol);
    }
    *lp = '\0';			/* make sure we have end marked */

    TRACE(("Salted TEXT:%u:%s\n", (unsigned) (lp - line),
	   visibleChars(line, (unsigned) (lp - line))));

    scp->data_length = (size_t) (lp - line);
}